2

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 メソッドを「再利用」し、コピー コンストラクターをインラインで宣言できるようにする回避策を提案できる人はいますか?

4

3 に答える 3

1

ネイティブプロジェクトでVS2008を使用してサンプルをコンパイルしようとしました。全く問題なし。しかし、管理対象プロジェクトで試したところ、同じエラーが発生しました。したがって、これは明らかにマネージコードと関係があります。

C ++ / CLIは標準外の拡張機能であるため、予期しない動作をするのも不思議ではありません。残念ながら、管理対象環境でコピーコンストラクターを実行する必要がある理由を指摘できるわけではありません。

于 2010-04-07T11:02:05.793 に答える
0

VS2008 で匿名名前空間を使用してコードを試してみたところ、コンパイルとリンクが正常に行われました。

本当にCarどこにも言及していないことを確認してください。

Carの定義を完全に消去するとどうなりますか? すべてがまだコンパイルされますか?

于 2010-04-07T10:43:31.487 に答える
0

そうですね、コピー コンストラクターは必要ですが、デフォルト コンストラクターは必要ないようです。この例は次のようになります。

std::vector <Car> v;

実際に入力するかどうか。

于 2010-04-07T10:35:56.607 に答える