是O.K.在其体外定义类模板的虚函数?虚函数不能内联,但为了避免编译单元中的多个定义,它们应标记为inline
(假设模板头将包含在多个源文件中)。另一方面,编译器可以自由地忽略inline
,所以这似乎是有效的。举个例子,下面的代码是正确的:
template <typename T>
class C
{
public:
virtual void f(T val);
};
template <typename T>
inline
void C<T>::f(T val)
{
//definition
}
BTW gcc(3.4.2)允许在定义函数inline
之前省略f(T val)
,但不能在常规类的类似函数之前省略{{1}}。这只是gcc的行为吗?
答案 0 :(得分:10)
是的,即使没有inline
也没关系。它对普通成员函数和静态变量的作用相同:
// everything in the header:
template <class T>
class A
{
static int i;
};
template <class T>
int A<T>::i=0;
标准报价:(3.2 / 5)
类类型(第9条),枚举类型(7.2),内联函数可以有多个定义 外部链接(7.1.2),类模板(第14章),非静态函数模板(14.5.6),静态数据成员 类模板(14.5.1.3),类模板的成员函数(14.5.1.1),或模板专用化 在程序中没有指定一些模板参数(14.7,14.5.5),只要每个定义 出现在不同的翻译单元中,并且如果定义满足以下要求......
要求基本上说两个定义必须相同。
在常规课程中不起作用。整个计划中最多只能有一个定义。
答案 1 :(得分:5)
您可以在同一标头中定义class
定义之外的模板方法,而无需使用inline
且不会收到多个定义错误。
这是因为模板函数本身不生成定义,如果它不是完全专业化的。为证明我的观点,以下内容:
void C<int>::f(int)
{
}
将导致链接器错误,因为该函数在这种情况下具有定义。 (如果您将其包含在多个翻译单元中。如果您将其标记为内联:
inline void C<int>::f(int)
{
}
错误不再发生。
答案 2 :(得分:3)
您可以在那里定义函数,只要需要实例化相关函数的任何代码在编译时(而不是链接时)都能看到该代码。
将模板分成2个文件是很常见的,一个是传统的标题,第二个是实现,就像非模板化函数及其实现一样。唯一的区别是你需要#include模板实现文件以及你想要使用它时的标题。