5

I've a static stl map in a C++ class and have another static member function to return a constant pointer to the object in the map. This map is common to all objects in the class.

Only problem is, I need to search this map and set it from another class, which is in a different .cpp/.h file, and I get unresolved external symbol when I try and compile them in vs2010. The methods are defined in the Timestream class as

static void setRoomList(std::map<std::string, RoomDescription> rl);
static RoomDescription * getRoom(std::string ref); 

both functions are public, so there should be no access issues. These functions are defined as normal in the Timestream.cpp file i.e.,

RoomDescription * Timestream::getRoom(std::string ref)
{
    std::map<std::string, RoomDescription>::iterator cIter= roomList.find(ref);

    if(cIter!=roomList.end())
        return &(cIter->second);

    return NULL;
}

I'm trying to call this like

RoomDescription *r =Timestream::getRoom("Bathroom")

from the other class. Other posts on the web seem to talk about using extern, but I'm not sure about that. I don't see why this should be any different to calling any other member function from a different class?

Thanks, James

EDIT: Yes, I've declared

std::map<std::string, RoomDescription> roomList;

at the top of the Timestream.cpp file. In the header it's defined as

static  std::map<std::string, RoomDescription> roomList;

I've included the header of RoomDescription in the header of the class I'm trying to call these methods from.

The error I get is this

Import.obj : error LNK2019: unresolved external symbol "public: static void __cdecl Timestream::setRoomList(class std::map,class std::allocator >,class RoomDescription,struct std::less,class std::allocator > >,class std::allocator,class std::allocator > const ,class RoomDescription> > >)" (?setRoomList@Timestream@@SAXV?$map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@VRoomDescription@@U?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@VRoomDescription@@@std@@@2@@std@@@Z) referenced in function "public: int __thiscall Import::getRoomData(void)" (?getRoomData@Import@@QAEHXZ)

Timestream.obj : error LNK2001: unresolved external symbol "private: static class std::map,class std::allocator >,class RoomDescription,struct std::less,class std::allocator > >,class std::allocator,class std::allocator > const ,class RoomDescription> > > Timestream::roomList" (?roomList@Timestream@@0V?$map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@VRoomDescription@@U?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@VRoomDescription@@@std@@@2@@std@@A)

Martin York
  • 257,169
  • 86
  • 333
  • 562
James
  • 1,764
  • 5
  • 31
  • 49
  • 3
    Possibly you didn't define roomList variable in .cpp file. Anyway, show exact code and error message. – Alex F Aug 28 '12 at 14:41
  • Possible Duplicate (maybe): http://stackoverflow.com/questions/7092765/what-does-it-mean-to-have-an-undefined-reference-to-a-static-member – Mankarse Aug 28 '12 at 14:42
  • Where is setRoomList definition? – Alex F Aug 28 '12 at 15:04
  • There were two problems, std::map roomList; should have been std::map Timestream::roomList; and incredibly enough I'd forgotten to define the setRoomList method, one of my more dim moments. Thanks for your help with this. Always find myself having issues with static variables/methods. – James Aug 29 '12 at 10:12

2 Answers2

5

You need to add:

std::map<std::string, RoomDescription> Timestream::roomList;

to Timestream.cpp, or whatever your implementation file is called.

This will define the static member. In the header file, you only declare it.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
4

I'm guessing that the unresolved external symbol is roomList; this is an important piece of information that's included in the error message. And, presumably, roomList is the static member that's been declared in the class definition. If those assumptions are right, then the cause of the error is that the code doesn't have a definition of roomList.

In general, static members must be declared in the class definition and defined in a source file:

// foo.h:
class C {
    static int data;
};

// foo.cpp:
int C::data = 42;

This has nothing to do with accessing the static member from another class. You'd get the same error if you tried to access it from the class that declares it.

EDIT: from the newly-posted error messages, there are two missing names: setRoomList and roomList. Note that roomList is a member of Timestream, and must be defined as such, that is, it's definition must include Timestream::. As shown above, it is simply a global data object, not a member of Timestream. The problem with setRoomList may be the same.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165