【问题标题】:Template definitions outside class body类主体之外的模板定义
【发布时间】:2012-04-29 23:25:00
【问题描述】:

可以吗?在其主体之外定义类模板的虚函数?虚函数不能内联,但为避免在编译单元中有多个定义,应将它们标记为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) 允许在定义函数f(T val) 之前省略inline,但不能在普通类的类似函数之前省略。只是gcc的行为吗?

【问题讨论】:

  • @jpalecek 在这个特定的例子中,是的。
  • @doc - 虚函数可以声明为inline(但这里不需要)。编译器只是很难确定函数何时可以内联。

标签: c++ templates virtual inline


【解决方案1】:

是的,即使没有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),前提是每个定义 出现在不同的翻译单元中,并且定义满足以下要求...

要求基本上是说这两个定义必须相同。

它不适用于常规课程。整个程序最多只能有一个定义。

【讨论】:

    【解决方案2】:

    您可以在 class 定义之外的同一标头中定义模板方法,而无需使用 inline 并且不会收到多个定义错误。

    这是因为模板函数本身不会生成定义,如果它不是完全专用的。为了证明我的观点,以下内容:

    void C<int>::f(int)
    {
    }
    

    将导致链接器错误,因为在这种情况下函数具有定义。 (前提是您将其包含在多个翻译单元中。如果您将其标记为内联:

    inline void C<int>::f(int)
    {
    }
    

    错误不再发生。

    【讨论】:

      【解决方案3】:

      您可以在那里定义函数,只要任何需要实例化相关函数的代码在编译时(而不是链接时)都能看到该代码。

      将模板分成 2 个文件是很常见的,一个是传统的标头,第二个是实现,与非模板化函数及其实现一样。唯一的区别是需要在使用的时候#include模板实现文件以及header。

      【讨论】:

        猜你喜欢
        • 2021-09-26
        • 2021-02-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-13
        • 2012-10-04
        • 1970-01-01
        • 2022-07-22
        相关资源
        最近更新 更多