2

我在 Visual Studio 2008 C++ 编译器中遇到了以下烦人且看似不正确的行为:

假设我有一个类库 - Car.lib - 它使用“Car”类,头文件名为“Car.h”:

class Car
{
    public:
    void Drive()
    {
        Accelerate();
    }

    void Accelerate();
};

我实际上想要做的是使用 Car 标头(用于其他一些功能),但不必与 Car.lib 本身链接(实际的类不称为“Car”,但我正在清理这个示例)。

如果我在用于构建托管 C++ .dll 的 .cpp 文件中#include "Car.h",但从不引用 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

请注意,我已经在匿名命名空间中声明了整个内容,因此在任何情况下都无法从 .DLL 中导出 Car 函数。

我可以肯定地保证 Car 不会在其他任何地方被引用,因为我只是创建了这个类并从 scatch 中输入了定义。“真正的”类是一个不同的名称。

离线声明复制构造函数没有区别。即以下也无法链接:

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

好吧,看起来有些东西需要复制构造函数,但不需要默认构造函数。这方面的一个例子是:

std::vector <Car> v;

无论您是否实际填充它。

于 2010-04-07T10:35:56.607 回答
0

刚刚使用 VS2008 使用匿名命名空间尝试了您的代码,它可以正常编译和链接。

确保你真的没有提到Car任何地方。

如果您Car完全删除 的定义会发生什么?一切都还在编译吗?

于 2010-04-07T10:43:31.487 回答