我有几个构建到静态库的模块。根据需要,一些静态库可能会被链接,而另一些可能不会。其中一些静态库具有具有静态 Init() 方法的类。“核心”库,也被链接,也有一个 Init() 方法,以前它包含多行,如:
Telephony::Init();
但是,如果 Telephony 不打算链接到这个特定的应用程序,我不想修改核心库的代码来删除该行。所以我尝试了类似的东西:
class init_hook_base
{
public:
inline init_hook_base() { Core::AddInitHook(this); }
protected:
friend class Core;
virtual ~init_hook_base() {}
virtual void operator()() const = 0;
};
template<class T>
class init_hook_t
{
protected:
void operator()() const
{
T::Init();
}
};
然后我将创建一个静态全局变量,例如:
static init_hook_t<Telephony> telephony_init_hook;
在 Telephony 库中,这将允许 Core 在编译时不知道它的情况下间接调用 Telephony::Init。不幸的是,telephony_init_hook 没有被构造,我假设它在链接阶段被剥离,尽管它的构造函数有副作用。做类似的事情:
void Telephony::Init() { (void)telephony_init_hook; }
也不起作用,因为就链接器而言,Init 本身也是无法访问的。有没有办法用 C++ 实现这种模块化风格?编译器特定的选项是可行的,只要 GCC 和 VC++ 都有对应的选项。谢谢。
注意:对于那些关心影响 Core::AddInitHook 的全局初始化顺序的人:
std::vector<init_hook_base*>* Core::init_hooks; //THESE ARE DELIBERATELY UNINITIALIZED!!!
unsigned char Core::init_hooks_ptr_hash[20];
bool Core::inited = false;
void Core::EnsureInitHooksContainerReady()
{
unsigned char current_hash[20];
sha1::calc(&init_hooks, sizeof(init_hooks), current_hash);
if (memcmp(current_hash, init_hooks_ptr_hash, 20))
{
//the hash is incorrect, so init_hooks is not yet initialized;
init_hooks = new std::vector<init_hook_base*>();
sha1::calc(&init_hooks, sizeof(init_hooks), init_hooks_ptr_hash);
}
}
void Core::AddInitHook(init_hook_base* init_hook)
{
EnsureInitHooksContainerReady();
init_hooks->push_back(init_hook);
}
void Core::Init()
{
assert(!inited);
PlatformInit();
EnsureInitHooksContainerReady();
for (auto init_hook_base : *init_hooks) {
(*init_hook_base)();
}
}