4

これが.hです:

class Logger
{
private:
    static int mTresholdSeverity;

public:
    static __declspec(dllexport) void log(const char* message);
    static __declspec(dllexport) void logFormat(const char* format, ...);

    static __declspec(dllexport) int getTresholdSeverity() { return mTresholdSeverity; }
    static __declspec(dllexport) void setTresholdSeverity(int tresholdSeverity) { mTresholdSeverity = tresholdSeverity; }
};

そして.cpp:

#include "Logger.h"
#include <cstdarg>

int Logger::mTresholdSeverity = 200;

void Logger::log(const char* message)
{
    //...
}

void Logger::logFormat(const char* format, ...)
{
    //...
}

このエラーが発生します:
エラーLNK2001:未解決の外部シンボル "private:static int TransformationViewer_Utility_Logging :: Logger :: mTresholdSeverity"(?mTresholdSeverity @ Logger @ TransformationViewer_Utility_Logging @@ 0HA).. ..

明らかに、mTresholdSeverityは初期化されています。getTresholdSeverity()とsetTresholdSeverity()をコメントアウトするか、それらの定義を.cppファイルに移動すると、エラーは削除されます。

ヘッダーファイルで定義された静的メソッド(getTresholdSeverity()またはsetTresholdSeverity())が静的変数(mTresholdSeverity)を使用するときに、リンクエラーが発生するのはなぜですか?

4

3 に答える 3

3

仕組みは次のとおりです。

すべてのDLL(またはEXE)またはその他の完全な「完全にリンクされた」バイナリには、C++クラスの静的データメンバーを含む静的変数を含むすべての参照名の定義が必要です。

これらは、アプリケーション内のDLL間で分離されます。つまり、この変数値は、参照するDLLによって異なります。関数をCPPファイルに移動すると、別の処理が実行されます。EXEではなくDLLの変数のコピーが表示されるようになります。

作成したものをコンパイルするには、すべてのユーザーバイナリにCPPか​​らの定義が1か所に存在する必要があります。つまり、DLLとDLLのユーザー(EXEまたはDLL)には、この定義を持つ1つのCPPファイルが必要です。

これは非常に面倒です。特に、シングルトンパターンを不可能にし(プログラム内のすべてのユーザーに共有データオブジェクトを持たせる)、DLLの各コピーに独自の静的状態を持たせる必要があるためです。このような問題は、ダイナミック*ロード*ライブラリであるDLLを使用するWindowsでのみ発生します。UNIXシステムには、共有オブジェクト(SO)と呼ばれる別のテクノロジーがあります。これらは、真の動的リンクをサポートします。つまり、実行時に外部名を解決するためにリンカーを実行します。

于 2012-09-01T17:08:27.383 に答える
0

問題はmThresholdSeverity、DLLからエクスポートされないことですが、2つのアクセサーはインラインで定義されているため、呼び出される場所はどこでも、を見ることができる必要がありますmThresholdSeverity。2つの解決策があります:mThresholdSeverityDLLからエクスポートする(申し訳ありませんが、頭のてっぺんからそれを行う方法を覚えていません)、またはアクセサーを非インライン関数にして、DLLで定義し、からエクスポートしますDLL。

于 2012-09-01T16:34:51.507 に答える
0

これがノイズで失われないようにするためです。アクセサを通常の非インライン関数に変更し、静的データメンバーと同じソースファイルで定義できます。それらをエクスポートする限り、どこからでも呼び出すことができ、静的データに問題なくアクセスできます。

于 2012-09-01T18:57:46.180 に答える