I am trying to use factory mode to create some derived class.
Here are the details about it:
Purpose:
There are two classes DerivedA and DerivedB derived from BaseClass. Class DerivedA is defined in derived_class_A.h/cpp and DerivedB in derived_class_B.h/cpp.
Also there is a factory class Factory in factory.h/cpp to create DerivedA or DeriveB.
Our purpose is that, the Factory is allow to create DerivedA if and only if derived_class_A.cpp is compiled, meanwhile we don't want to have any information about DerivedA in the factory.h/cpp.
So we cannot use switch case(){...} to call new DerivedA() in the factory, nor can we use MACROS to distinguish DerivedA and DerivedB.
Our Implementation
In the Factory class, we have a static method:
template<class classname> Factory::RegisterClass<classname>(int key);
It uses a std::map to map the key keyA to the new DerivedA() function, and keyB to new DerivedB() function.
Then in the BaseClass* Factory::CreateClass(int Key) method, it can
get the creator of DerivedA/DerivedB according to the key.
In derived_class_A.cpp, we are trying to calling the RegisterClass during the library loading. Here is the way we use:
class tempClassA { tempA() { Factory::RegisterClass<DerivedA>(keyA); } };
static tempClassA tempA;
In this way, if derived_class_A.cpp exists, the RegisterClass of DerivedA will be called when the static variable tempA is initialized.
If derived_class_A.cpp is not compiled, then static variable tempA doesn't exist and the RegisterClass of DerivedA won't be called. This is the result we expected.
Issues:
This method works perfectly when we build the code as a shared library directly, or as an executable.
However, when we build it to a static library and then linked into a final shared library with other libs, seems that the derived_class_A.o is not linked into the shared library.
We think it is caused by the fact that no definitions in derived_class_A.cpp is referred explicitly in other files. The Factory class call the creator of DerivedA implicitly.
Here is an experiment to prove that it is not linked:
- We declare a function using "
extern", but doesn't implement it. We call this fake function inderived_class_A.cpp, and it doesn't report any linking error either in the static library building or latter building the static lib into the final shared library. - If we define a variable "
int A" inderived_class_A.cppand refer it using "extern int A" infactory.cpp. (In fact we can't do that in our project since we can't including any information fromderived_class_A.cppinfactory.cpp.) In this casederived_class_A.owill be linked as it will report an linking error about the fake function we added in step 1.
Questions
- So can I force a file to be linked in the final library even non of its definition is referred external?
- If not, is there any other choice to implement this mechanism? I know on Linux
__attribute__((constructor))can guarantee theregisterClassfunction called when the library is loaded. But I didn't find any similar tools on Windows VS.
Thanks a lot for watching this.