In a nutshell I am trying to write a program that will connect to a database, query several tables for various sets of data that will then be transformed into XML that is stored into a file on the local hard disk. My first thought process to solve this problem was to create classes that would be used to contain one row of data returned for each result set. I would create a base class that would define the common behavior between each derived class, while the derived classes would handle anything that is specific to the type of result set. I then decided that I wanted to use a template container to collect each row so that I could easily iterate, sort, transform into XML each of the rows returned.
Now, I am using basic polymorphism for the base and derived classes. For the template container, I am declaring the template and then defining my specialized function definitions. The program compiles fine, but I get undefined symbols when the program enters the linking stage.
Here is a simplified example of what I am trying to do:
#include <iostream>
using namespace std;
// A common base class that will be branched into multiple derived classes
class Base {
protected:
Base() {
}
virtual ~Base() {
}
int _foo;
};
// One example deriviation of Base
class Derived : public Base {
public:
Derived();
virtual ~Derived();
int getFoo();
};
Derived::Derived() {
}
Derived::~Derived() {
}
int Derived::getFoo() {
return _foo;
}
// A template container that will be specialized to only accept
// classes derived from Base (that's the hope, anyway)
template <typename T>
class Container {
public:
Container();
~Container();
};
template <>
Container<Base>::Container() {
}
template <>
Container<Base>::~Container() {
}
int main() {
// GCC (4.2)/VSE08 compiles the code just fine, but the linker complains
// as if Derived doesn't inherit from Base.
Container<Derived> dc;
cout << &dc << endl;
return 0;
}
I have tried this in both Visual Studio Express 2008 on Windows XP SP2, and with GCC 4.2 on Mac OS X 10.6.4, and both compilers report the same problem(s):
------ Build started: Project: Sandbox, Configuration: Debug Win32 ------
Linking...
LINK : warning LNK4076: invalid incremental status file 'C:\Documents and Settings\kstanley\My Documents\Visual Studio 2008\Projects\Strayer - CIS326\Debug\Sandbox.ilk'; linking nonincrementally
main.obj : error LNK2019: unresolved external symbol "public: __thiscall Container<class Derived>::~Container<class Derived>(void)" (??1?$Container@VDerived@@@@QAE@XZ) referenced in function _main
main.obj : error LNK2019: unresolved external symbol "public: __thiscall Container<class Derived>::Container<class Derived>(void)" (??0?$Container@VDerived@@@@QAE@XZ) referenced in function _main
C:\Documents and Settings\kstanley\My Documents\Visual Studio 2008\Projects\Strayer - CIS326\Debug\Sandbox.exe : fatal error LNK1120: 2 unresolved externals
Build log was saved at "file://c:\Documents and Settings\kstanley\My Documents\Visual Studio 2008\Projects\Strayer - CIS326\Sandbox\Debug\BuildLog.htm"
Sandbox - 3 error(s), 1 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
and
h223:solr_import kstanley$ g++ c.cpp
Undefined symbols:
"Container<Derived>::~Container()", referenced from:
_main in cc1iB1E2.o
_main in cc1iB1E2.o
"Container<Derived>::Container()", referenced from:
_main in cc1iB1E2.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
I believe that I understand the Why of the problem: after the compiler does its "magic" with the specialized template, the linker only sees the call to "Container<Derived>", but doesn't know that Derived is also Base (I know that there is a lot that goes into template specialization, and that I am surely over simplifying everything). My question to the community is how can I achieve something like what I am trying to do above so that a) I can have separate classes to work with the different result sets, b) use templates (mostly for the practice), and c) use specialization so the template only accepts specific types?
Thank you in advance,
Ken