devxlogo

Derive from STL Map

Derive from STL Map

Question:
I created my own map class (called it Mapper) by creating a template class and deriving from STL map container class. I did so because I wanted to have some extra user-defined methods in this class. I don’t have any problems compiling if I only use the methods provided by the STL map class. However, when I try to make a call to one of the new methods in Mapper, I get the following linking error:

--------------------Configuration: mapfunc - Win32 Debug--------------------Compiling...runmapper.cppLinking...runmapper.obj : error LNK2001: unresolved external symbol 
"public: int __thiscall Mapper::SmartMatch(class
std::basic_stringshort>,class std::allocator > const &)" (?
SmartMatch@?$Mapper@H@@QAEHABV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@@Z)Debug/mapfunc.exe : fatal error LNK1120: 1 unresolved externalsError executing link.exe.mapfunc.exe - 2 error(s), 0 warning(s)

By the way, runmapper.cpp is the driver program and mapfunc is the project name. I have three user-defined methods (one of them is SmartMatch(key)) that when I try to call, from the driver program, give me the same compilation error (linking error).

Answer:
The compiler must see the definition, not just the declaration, of a template in order to instantiate it. It looks like you #included only the declaration (i.e., the prototype) of your added member function:

int Mapper::SmartMatch(std::wstring); //  prototype

The compiler needs to see its definitions (implementation), too. If you’re using Visual C++, my advice is to implement template member functions inline, inside the header file that declares the class template.

Note that deriving from STL containers is usually a bad idea because STL containers have no virtual destructors or virtual member functions. This can cause undefined behavior in certain conditions, for example, if you pass a pointer to std::map which actually points to a class derived from std::map and has its own destructor. In this case, the derived class’s destructor isn’t called:

// mapper is derived from std::mapstd::map  * p new mapper ; delete p; /*undefined behavior; only map ::~map  called*/

If you need to extend STL’s functionality, it’s better to use containment rather than public inheritance.

devx-admin

Share the Post: