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.cpp
and 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.cpp
infactory.cpp
.) In this casederived_class_A.o
will 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 theregisterClass
function called when the library is loaded. But I didn't find any similar tools on Windows VS.
Thanks a lot for watching this.