2017-10-17 127 views
1

我正在試驗專門的析構函數。此代碼是完全有效的,並編譯就好了:如果我把類,並在一個單獨的文件「Cat.h」的析構函數和做Main.cpp的#include "Cat.h"「已經定義的析構函數」與專門的析構函數

#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; 
} 

不過,我得到一個鏈接錯誤:LNK2005 "public: __thiscall Cat<int>::~Cat<int>(void)" ([email protected]@@[email protected]) already defined in Cat.obj。爲什麼?

+3

你不能只專注於類模板的一個成員函數。你必須專門研究整個班級。 – navyblue

+0

這不是重複的。我將我的代碼放在標題中,而不是cpp中。 – Valentin

+0

@navyblue 1.析構函數是我定義的唯一函數。或者你的意思是我還必須專門處理默認生成的內容? 2.爲什麼在第一種情況下編譯? – Valentin

回答

3

這聽起來像你具備以下條件:

template <> 
Cat<int>::~Cat() 
{ 
    std::cout << "int" << std::endl; 
} 
在包括兩個翻譯單元一個頭文件

。一個函數模板的顯式特化是一個非內聯函數(C++ 14 [temp.expl.spec]/12);所以這是一個ODR違規。

如果你在同一個地方實現了一個非模板成員函數(或者一個自由函數),那麼你會得到同樣的錯誤:兩個翻譯單元最終都有一個函數的副本,即使這兩個副本是相同的。

要解決此問題,請在template<>之前加上關鍵字inline


關於爲類模板的成員函數提供顯式特化的合法性有一些討論。相信這是正確的,但有限制,根據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.

在程序是在完美的位置:在課堂定義之後立即。在聲明至少遇到專業化之前,類可能已經實例化時,會發生冒險的小問題。

+0

您還需要聲明專業化權限?沒有這個,我認爲這在技術上也是UB。 – GManNickG

+0

@GManNickG我不這麼認爲 - 函數的定義也是一個聲明。規則是必須在任何特定事物的實例化之前聲明明確的特化;但該聲明也可以是一個定義 –