模板化类中函数的多重定义

时间:2013-07-10 16:12:53

标签: c++ templates

我看到了一件有趣的事情,却无法理解为什么。

template<class dataType>
Class A
{
AFnc();
}

template<> A<int>::AFnc() { }

仅使用专用模板会生成错误,表示同一功能的多个定义。它说它是在同一个地方生成的。 但是,如果我添加

template<class dataType>
A<dataType>::AFnc()
{
}

然后它摆脱了错误。

为什么?有人可以解释一下这种行为。

2 个答案:

答案 0 :(得分:3)

(您需要清理语法。我假设实际代码没有所有这些语法错误。)

模板函数的显式特化不再是模板,因为它不再依赖于任何模板参数。从一个定义规则(ODR)的角度来看,它是一个“普通”的功能。并且,作为“普通”函数,它必须在头文件中声明,并且在某些实现文件中只需定义一次。您显然在头文件中定义了您的专业化,如果头文件包含在多个翻译单元中(例如您的“多重定义”错误),则会导致ODR违规。

在您的示例中,template<> void A<int>::AFnc()(我添加void作为返回类型)不再是模板。这意味着此定义

template<> void A<int>::AFnc() { }
必须将

从头文件移动到某个实现文件。同时,在头文件中,您必须为此函数保留一个非定义声明

template<> void A<int>::AFnc(); // <- note, no function body

让编译器知道存在这种特化。

一般情况下,请记住一个简单的规则:如果您的函数模板仍然依赖于某些未指定的模板参数,那么它是一个真正的模板,它必须在头文件中定义。但是一旦你“修复”了所有参数(通过显式特化),它就不再是模板了。它成为普通函数,必须在头文件中声明,并且在某些实现文件中只需定义一次。

P.S。以上适用于非内联函数。内联函数可以(通常应该是)在头文件中定义。

P.P.S。相同的逻辑适用于模板类的静态数据成员的显式特化。

答案 1 :(得分:1)

我想,你将明确的实例化放在头文件中。然后,它的代码将在包含该文件的每个翻译单元中发出。只需移动此代码

即可
template<> A<int>::AFnc() { }

到.cpp文件,它只会发出一次。 你不会用模板方法得到这个错误,因为隐式实例化的规则是不同的。