如果我会这样写:
// A.h
#ifndef A_h
#define A_h
class A
{
public:
void f();
};
void A::f()
{
}
#endif //A_h
// B.cpp
#include "A.h"
void foo()
{
A a;
a.f();
}
// C.cpp
#include "A.h"
void bar()
{
A b;
b.f();
}
// main.cpp
#include "B.cpp"
#include "C.cpp"
using namespace std;
int main()
{
foo();
bar();
return 0;
}
我收到这样的链接器错误:
error LNK2005: "public: void __thiscall A::f(void)" (?f@A@@QAEXXZ) already defined in B.obj
为什么当 A
类是类模板时不会发生同样的问题?最终它在编译过程中变成了一个普通类(一个非模板类),对吧?出于这个原因,我期望与非模板类的行为相同,即链接器错误。
最佳答案
这里有两个独立的效果:
越界的成员函数定义是正常的函数定义,根据一个定义规则 (ODR),它必须在链接中恰好出现一次。内联定义的成员函数是隐式
内联
,并且 ODR 允许重复内联函数定义:也就是把下面的代码放在一个header中,重复包含就可以了:
struct Foo { void bar() {} // "inline" implied };
但如果定义不一致,它必须在单个翻译单元中。
函数模板可以重复定义,即使它们不是内联的。一般来说,模板机制已经需要处理模板的重复实例化,并在链接时处理重复数据删除。
类模板的成员函数本身就是函数模板,因此是否将它们声明为
内联
并不重要。
关于c++ - 为什么模板没有重新定义,为什么都写在头文件里了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36841401/