0

次のようなスキームがあるとします。

qqqapi.h:

int register_qqq(Qqq* klass);

qqqalpha.cpp:

QqqAlpha::QqqAlpha(...) : Qqq(...) { }

QqqAlpha instance;
int dummy = register_qqq(&instance);

qqqbeta.cpp:

QqqBeta::QqqBeta(...) : Qqq(...) { }

QqqBeta instance;
int dummy = register_qqq(&instance);

このようにして、ソース ファイルとヘッダー ファイルをコピーし、適切な識別子を変更するだけで、新しい qqq タイプを作成できます。リストに手動で何かを追加する必要はありません。

このパターンはどのように呼ばれますか? そのようなことを適切に実装するための推奨事項はありますか?

4

1 に答える 1

1

このスキームの主な問題は、C++ 実装が翻訳単位全体を処理することです。

何百もの翻訳単位を含む静的ライブラリを考えてみましょう。コンパイラとリンカが知る限り、プログラムは 1 つまたは 2 つしか使用していません。レジストリ オブジェクトへの自動登録によって、プログラムが実際に 5 つのユニットを使用していることを彼らはほとんど知りません。

そのため、リンカは、ライブラリが提供するすべての翻訳単位を削除します。ただし、関数の呼び出しや変数の参照など、コードで直接使用される 1 つまたは 2 つの翻訳単位は除きます。

結果: シングルトン レジストリに本来あるべきものが含まれていない不可解な実行時エラー。

これがおそらく、パターン/イディオム/whatchamacallit がほとんど使用されない理由です。オブジェクト コード ファイルに対しては問題なく機能します。これは、リンカに何を含めるかを明示的に指示しているためです。静的ライブラリではうまく機能しません。


ベスト プラクティスは、コードを介して、場合によってはドキュメントを介して、翻訳単位から何かが呼び出されるか、参照されるようにすることmainです。

これにより、目に見える依存関係が存在することが保証されるため、翻訳単位は削除されません。


私はこれに一般的に使用される名前を知りません。昔、別の言語でモジュールエンベロープと呼ばれるものがありました。これは、モジュールの初期化とクリーンアップを担当する静的オブジェクトのコンストラクタとデストラクタの実行と考えることができます。しかし、C++ はそれをサポートしていません。私が思い出したように、近年この用語をグーグルで検索しても、関連するヒットはありませんでした。それに関する情報はすべて消えてしまったようです...

于 2012-12-27T23:06:49.393 に答える