c++ - "Destructor already defined"带有专门的析构函数

标签 c++ templates template-specialization

我正在试验专门的析构函数。这段代码完全有效并且编译得很好:

#include <iostream>

using namespace std;

template <typename T>
class Cat
{
public:
    ~Cat();
};

template <typename T>
Cat<T>::~Cat()
{
    std::cout << "T" << std::endl;
}

template <>
Cat<int>::~Cat()
{
    std::cout << "int" << std::endl;
}


int main()
{
    Cat<int> c1;
    Cat<float> c2;
    return 0;
}

但是,如果我将类和析构函数放在单独的文件“Cat.h”中并执行 #include "Cat.h"在 Main.cpp 中,我收到一个链接器错误:LNK2005 "public: __thiscall Cat<int>::~Cat<int>(void)" (??1?$Cat@H@@QAE@XZ) already defined in Cat.obj .为什么?

最佳答案

听起来您有以下情况:

template <>
Cat<int>::~Cat()
{
    std::cout << "int" << std::endl;
}

在包含在两个翻译单元中的头文件中。函数模板的显式特化是非内联函数 (C++14 [temp.expl.spec]/12);所以这是 ODR 违规。

如果你在同一个地方实现了一个非模板成员函数(或一个自由函数),你会得到同样的错误:两个翻译单元最终都有一个函数的拷贝,这是不允许的,即使两个拷贝是相同的。

要解决此问题,请输入关键字 inline之前 template<> .


评论中有一些关于为类模板的成员函数提供显式特化的合法性的讨论。我相信这是正确的,根据 C++14 [temp.expl.spec]/6 进行限制:

If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required. If the program does not provide a definition for an explicit specialization and either the specialization is used in a way that would cause an implicit instantiation to take place or the member is a virtual member function, the program is ill-formed, no diagnostic required.

此外,第 7 节:

The placement of explicit specialization declarations for function templates, class templates, variable templates, member functions of class templates, static data members of class templates, member classes of class templates, member enumerations of class templates, member class templates of class templates, member function templates of class templates, static data member templates of class templates, member functions of member templates of class templates, member functions of member templates of non-template classes, static data member templates of non-template classes, member function templates of member classes of class templates, etc., and the placement of partial specialization declarations of class templates, variable templates, member class templates of non-template classes, static data member templates of non-template classes, member class templates of class templates, etc., can affect whether a program is well-formed according to the relative positioning of the explicit specialization declarations and their points of instantiation in the translation unit as specified above and below. When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation.

在您的程序中,它位于完美的位置:紧接在类定义之后。当类可能在声明至少遇到专门化之前实例化时,就会发生危险情况。

关于c++ - "Destructor already defined"带有专门的析构函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46799417/

相关文章:

c++ - 我可以使用别名模板专门化一个类模板吗?

c++ - 向 CMake 引入新的编译器

c++ - VS COM 项目在 32 位编译但在尝试编译 64 位时抛出错误 C2259

c++ - 在模板类中使用 vector 迭代器

python - 如何使用 django 在生产服务器上修复模板不存在错误?

c++ - 模板特化类函数

c++ - 这个条件如何放在模板偏特化中?

C++在类里面添加标题让我很生气

.net - 开发交易应用程序

c++ - VC++ 模板编译器错误 C2244 : Unable to Match Function Definition to an Existing Declaration