链接内联虚拟方法

时间:2013-07-08 21:22:25

标签: c++

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()关键字(为什么!?)
乍一看,海湾合作委员会的行为似乎更有帮助/更直观。也许熟悉标准的人可以指出我在这里的正确方向。

  • 在这种情况下,两种编译器都具有一致行为吗?
  • 如果方法是非虚拟的,为什么VC ++可以工作?

// 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;
}

2 个答案:

答案 0 :(得分:5)

两个编译器都是正确的。您正在调用未定义的行为,对于每个7.1.2第2段都不需要诊断:

  

内联函数应在每个使用过的翻译单元中定义,并且在每种情况下都应具有完全相同的定义(3.2)。 ......如果在一个翻译单元中内联声明具有外部链接的功能,则应在其出现的所有翻译单元中内联声明;无需诊断。

GCC可以自由地做它所做的事情并为你提供一个可能正常工作的程序。 VC ++在拒绝代码方面同样有效。

答案 1 :(得分:3)

内联函数应该在每个使用过的翻译单元中都有一个定义,在您的情况下,main.cpp

中没有任何一个
  

内联函数的定义不必位于标题中   但是,由于内联函数的一个定义规则,   每个翻译都必须存在相同的函数定义   使用它的单位。

     

实现这一目标的最简单方法是将定义放入   头文件。

     

如果要将函数的定义放在单个源中   文件然后你不应该声明它内联。未声明的函数   内联并不意味着编译器不能内联函数。

来自@CharlesBailey

1 在这种情况下,两个编译器是否都具有一致行为?

从这个标准引用我们可以说在这个特定情况下VC是对的。

  

C ++标准,§3.2一个定义规则/ 3:内联函数应   在每个使用它的翻译单元中定义

感谢@Pixelchemist

2 如果方法是非虚拟的,为什么VC ++可以工作?

根据标准的非虚拟功能,不使用“一个定义规则”,因此可以按照自己的方式使用它。