Visual Studio 2008 C++ コンパイラで、次の迷惑で一見正しくない動作に遭遇しました。
「Car.h」というヘッダーを持つ「Car」クラスを使用するクラスライブラリー Car.lib があるとします。
class Car
{
public:
void Drive()
{
Accelerate();
}
void Accelerate();
};
私が実際にやろうとしているのは、(他のいくつかの機能のために) Car ヘッダーを使用することですが、Car.lib 自体とリンクする必要はありません (実際のクラスは「Car」とは呼ばれませんが、この例をサニタイズしています)。
マネージ C++ .dll のビルドに使用する .cpp ファイルに "Car.h" を #include し、Car を参照しないと、すべてが正常にコンパイルおよびリンクされます。これは、Car オブジェクトをインスタンス化しないためです。
ただし、次のとおりです。
namespace {
class Car
{
public:
Car(const Car& rhs)
{
Accelerate();
}
void Accelerate();
};
}
リンクエラーが表示されます:
Error 2 error LNK2001: unresolved external symbol "public: void __thiscall `anonymous namespace'::Car::Accelerate(void)" (?Accelerate@Car@?A0xce3bb5ed@@$$FQAEXXZ) CREObjectWrapper.obj CREObjectBuilderWrapper
すべてを匿名名前空間内で宣言したので、Car 関数を .DLL からエクスポートすることはできません。
Car が他の場所で参照されていないことを断固として保証できます。これは、このクラスを作成し、最初から定義を入力したからです。「本当の」クラスは別の名前です。
コピーコンストラクターをアウトオブラインで宣言しても違いはありません。つまり、以下もリンクに失敗します:
class Car
{
public:
Car(const Car& rhs);
void Accelerate();
};
Car::Car(const Car& rhs)
{
Accelerate();
}
たとえば、次のようにリンクしているため、これは特にコピー コンストラクター ノートと関係があります。
class Car
{
public:
Car()
{
Accelerate();
}
void Accelerate();
};
私は C++ 標準の第一人者ではありませんが、これは正しくないように思えます。確かに、コンパイラは、Car コピー コンストラクターを呼び出すコードを生成する必要さえなかったはずです。
この動作が正しいかどうかは誰でも確認できますか? C++ を使用してからしばらく経ちましたが、たとえば Visual Studio 6.0 ではこれが問題になることはなかったと思います。
マネージ C++ .dll をビルドしていることが原因である可能性があります。(後で: はい、これはまさに問題です。 /clr オプションは、この依存関係を導入しているようです)。
プロジェクトのビルドに使用されるコマンド ラインは次のとおりです。
/OUT:"..\..\bin\Release\CREObjectBuilderWrapper.dll" /INCREMENTAL:NO /NOLOGO /LIBPATH:"..\..\lib\qa\lib" /LIBPATH:"..\..\lib\release" /LIBPATH:"..\..\lib\VDB" /DLL /MANIFEST /MANIFESTFILE:"Release\ObjectBuilderWrapper.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"c:\Release\ObjectBuilderWrapper.pdb" /LTCG /DYNAMICBASE:NO /FIXED:No /MACHINE:X86 /KEYFILE:"c:\src\ObjectBuilderWrapper\\FI.snk" /ERRORREPORT:PROMPT CRERuntime.lib QA.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib
コピー コンストラクター内から Accelerate メソッドを「再利用」し、コピー コンストラクターをインラインで宣言できるようにする回避策を提案できる人はいますか?