类体外的模板定义

时间:2012-04-18 14:15:14

标签: c++ templates virtual inline

是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的行为吗?

3 个答案:

答案 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模板实现文件以及你想要使用它时的标题。