我在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方法,并且仍然可以内联声明复制构造函数吗?
答案 0 :(得分:1)
我试图在本机项目中用VS2008编译你的例子;完全没问题。但我已经尝试了一个托管项目,我得到了同样的错误。所以这显然与托管代码有关。
由于C ++ / CLI是标准之外的扩展,我们不应该怀疑它会做出一些意想不到的事情。不幸的是,我不能指出托管环境需要运行复制构造函数的原因。
答案 1 :(得分:0)
嗯,看起来某些东西需要复制构造函数,但不需要默认的构造函数。这方面的一个例子是:
std::vector <Car> v;
你是否真正填充它。
答案 2 :(得分:0)
刚刚使用VS2008的匿名命名空间尝试了您的代码,它编译和链接正常。
确保您实际上并未在任何地方引用Car
。
如果完全删除Car
的定义会怎样?一切还在编译吗?