静的ライブラリにビルドするモジュールがいくつかあります。必要に応じて、スタティック ライブラリの一部がリンクされている場合とリンクされていない場合があります。これらの静的ライブラリのいくつかには、静的 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)();
}
}