GCC 4.7.2编译此代码如下:
Obj::getNumber()
中对Obj::defaultNumber()
的引用已内联Obj::getNumber()
的正文是单独编译和导出的,可以从不同的翻译单元进行链接。VC ++ 2012在链接步骤失败:
Error 1 error LNK2001: unresolved external symbol "public: virtual int __thiscall Obj::getNumber(unsigned int)"
中main.obj
VC ++似乎在Obj::defaultNumber()
中内联调用,但未在符号表中导出getNumber()
。
VC ++可以通过以下方式之一进行编译:
inline
定义或getNumber()
关键字
virtual
声明中移除getNumber()
关键字(为什么!?)
// Obj.h
class Obj
{
public:
virtual int getNumber(unsigned int i);
virtual int defaultNumber();
};
// Obj.cpp
static const int int_table[2] = { -1, 1 };
inline int Obj::getNumber(unsigned int i)
{
return int_table[i];
}
int Obj::defaultNumber()
{
return getNumber(0);
}
// main.cpp
#include <iostream>
#include "Obj.h"
int main()
{
Obj obj;
std::cout << "getNumber(1): " << obj.getNumber(1) << std::endl;
std::cout << "defaultNumber(): " << obj.defaultNumber() << std::endl;
}
答案 0 :(得分:5)
两个编译器都是正确的。您正在调用未定义的行为,对于每个7.1.2第2段都不需要诊断:
内联函数应在每个使用过的翻译单元中定义,并且在每种情况下都应具有完全相同的定义(3.2)。 ......如果在一个翻译单元中内联声明具有外部链接的功能,则应在其出现的所有翻译单元中内联声明;无需诊断。
GCC可以自由地做它所做的事情并为你提供一个可能正常工作的程序。 VC ++在拒绝代码方面同样有效。
答案 1 :(得分:3)
内联函数应该在每个使用过的翻译单元中都有一个定义,在您的情况下,main.cpp
内联函数的定义不必位于标题中 但是,由于内联函数的一个定义规则, 每个翻译都必须存在相同的函数定义 使用它的单位。
实现这一目标的最简单方法是将定义放入 头文件。
如果要将函数的定义放在单个源中 文件然后你不应该声明它内联。未声明的函数 内联并不意味着编译器不能内联函数。
来自@CharlesBailey
1 在这种情况下,两个编译器是否都具有一致行为?
从这个标准引用我们可以说在这个特定情况下VC是对的。
C ++标准,§3.2一个定义规则/ 3:内联函数应 在每个使用它的翻译单元中定义
感谢@Pixelchemist
2 如果方法是非虚拟的,为什么VC ++可以工作?
根据标准的非虚拟功能,不使用“一个定义规则”,因此可以按照自己的方式使用它。