VS 2008恼人的复制构造函数链接依赖

时间:2010-04-07 10:28:34

标签: visual-studio-2008 c++-cli visual-c++-2008

我在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 copy构造函数的代码。

任何人都可以确认这种行为是否正确吗?自从我使用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方法,并且仍然可以内联声明复制构造函数吗?

3 个答案:

答案 0 :(得分:1)

我试图在本机项目中用VS2008编译你的例子;完全没问题。但我已经尝试了一个托管项目,我得到了同样的错误。所以这显然与托管代码有关。

由于C ++ / CLI是标准之外的扩展,我们不应该怀疑它会做出一些意想不到的事情。不幸的是,我不能指出托管环境需要运行复制构造函数的原因。

答案 1 :(得分:0)

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

std::vector <Car> v;

你是否真正填充它。

答案 2 :(得分:0)

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

确保您实际上并未在任何地方引用Car

如果完全删除Car的定义会怎样?一切还在编译吗?