如果它们是模板类,我通常只在标题内定义我的类.-如果是这种情况,我仍然喜欢在标题中拆分声明和定义:
template<class T>
class Foo
{
public:
Foo();
void fooFunc();
};
template<class T>
Foo<T>::Foo()
{
}
template<class T>
void Foo<T>::fooFunc()
{
}
该代码也编译。但是,如果我删除模板:
class Foo
{
public:
Foo();
void fooFunc();
};
Foo::Foo()
{
}
void Foo::fooFunc()
{
}
我的Foos功能出现重复的符号错误。我非常确定这应该有效,并且我很惊讶它没有。这是预期的行为吗?如果我在定义之前添加内联也可以。
答案 0 :(得分:6)
是的,这是预期的行为。
内联函数应分别编译到每个调用站点,因此复制没有问题。对于模板函数,编译器在目标文件中标记它们,以便链接器基本上忽略重复项,因为很难预测模板将在何处实例化或不实例化。
但传统功能预计只能定义一次。如果在头文件中定义一个,它将被编译到包含头的每个转换单元中,如果您有多个包含该函数副本的目标文件,则会在链接时导致“重复符号”错误。
答案 1 :(得分:0)
我想链接器知道在多个翻译单元中定义的类与在多个翻译单元中定义的模板化类之间的区别。对于前者,它会生成重复的符号错误,对于后者,它会将两个实例视为同一个实例,并且只使用其中一个实例。