我正在尝试使用Visual Studio 2012编译一个测试程序,该程序应链接到同事给我的test.lib文件。
编译在链接步骤停止,错误为LNK2019。缺少的符号是:
public: virtual __thiscall abc::Test::~Test(void)
使用实用程序dumpbin
,我发现在test.lib中定义了以下符号:
public: virtual __cdecl abc::Test::~Test(void)
这两个功能有什么区别?我该如何解决这个编译问题?我错过了一些编译标志吗?
答案 0 :(得分:1)
你没有错过旗帜。
Calling convention modifiers,例如__thiscall
和__cdecl
,会在内部修改函数的名称。因此,__thiscall abc::Test::~Test(void)
不与__cdecl abc::Test::~Test(void)
具有相同的功能。要解决此问题,请将__thiscall
更改为__cdecl
。
IIRC,__cdecl
是MSVC(Visual Studio编译器)的默认调用约定,因此如果您的同事没有指定任何特殊内容,则dumpbin会将该函数描述为具有{__cdecl
。 1}}调用约定。
<强>解释强>
与C不同,C ++函数,方法和对象的内部名称不与源文件中的相同。这称为name mangling(有时称为名称修饰)。名称修改允许重载函数,也就是说,有几个函数只有它们的参数类型,类/名称空间成员资格等不同。
假设我有以下C程序:
// Foo.c
#include <stdio.h>
void myPrint(void) {
printf("Hello, World!\n");
}
void myPrint(const char* str) {
printf(str);
}
int main() {
myPrint();
myPrint("Hello, World!\n");
}
如果您尝试将其编译为C代码:
$ gcc -o Foo Foo.c
Foo.c:7:6: error: redefinition of ‘myPrint’
但是如果你尝试将其编译为C ++:
$ g++ -o Foo Foo.c
它编译。</ p>
如果您尝试使用g++ -o Foo.s Foo.cpp -S -Os
查看程序集,您会发现void myPrint(void);
函数的错位名称为_Z7myPrintv
(最终v
代表void
),而void myPrint(const char*);
函数的错位名称为_Z7myPrintPKc
(PKc
:指向康斯坦特字母的指针)。
顺便说一句,函数的错位名称取决于您使用的编译器。使用MSVC(Visual Studio&#39; s编译器),void myPrint(const char*);
具有以下错位名称:?myPrint@@YAXPBD@Z
。