2014-01-11 48 views
1

我在爲模板編寫C++時遇到3個問題。看來VS2013可以編譯下面的代碼。C++中的一些基本模板問題

代碼在這裏:

//template_test.h

#include <iostream> 
using namespace std; 

template<class T> 
class mytest 
{ 
public: 
    void method(T input); 
    void common(); 
}; 

template <> 
class mytest<char> 
{ 
public: 
    void method(char input); 
    void common(); 
}; 


template<class T> 
void mytest<T>::method(T input) 
{ 
    cout << input << endl; 
} 


template<class T> 
void mytest<T>::common() 
{ 
    cout << "common" << endl; 
} 

//template_test.cpp

#include "template_test.h" 

void mytest<char>::method(char input) 
{ 
    cout << "char:" << input << endl; 
} 

void mytest<char>::common() 
{ 
    cout << "common" << endl; 
} 

//main.cpp

#include "template_test.h" 
using namespace std; 

int main() 
{ 

    mytest<char> test_char; 
    test_char.method('1'); 
    test_char.common(); 

    mytest<int> test_int; 
    test_int.method(1); 
    test_int.common(); 

    system("pause"); 

    return 0; 
} 

1.In執行mytest ::方法

template<class T> 
void mytest<T>::method(T input) 
{ 
    cout << input << endl; 
} 

我可以刪除第二個T表示短的表達嗎?我在VS2013中嘗試下面的代碼而不是原始的cpp,並且無法編譯。

template<class T> 
void mytest::method(T input) 
{ 
    cout << input << endl; 
} 

這似乎很奇怪,我需要使用它如此複雜的形式與這麼多的模板參數。

2.In h文件,我delclare類 'mytest的' 使用模板專門與

template <> 
class mytest<char> 
{ 
public: 
    void method(char input); 
    void common(); 
}; 

和各功能的實現是

//template_test.cpp

#include "template_test.h" 


void mytest<char>::method(char input) 
{ 
    cout << "char:" << input << endl; 
} 

void mytest<char>::common() 
{ 
    cout << "common" << endl; 
} 

我的問題是,當我將.h文件中的實現放在.cpp文件以外的非專業化模板類的實現中時,VS2013也會報告錯誤或代碼。

我知道非專業化模板類的聲明和實現應該在同一個頭文件中,因爲C++不應該允許在其他文件中顯示非專業化模板類。但爲什麼專業模板類的聲明和實現應該在不同的代碼文件中?

3.In頭文件

template<class T> 
class mytest 
{ 
public: 
    void method(T input); 
    void common(); 
}; 

template <> 
class mytest<char> 
{ 
public: 
    void method(char input); 
    void common(); 
}; 

很明顯,功能「公共」是專業化和非專業化模板類的公共部分。然而,專業化將專業化整個班級。我只想保留常用功能,所以不需要在專業化版本中編寫相同的功能。我不知道如何得到它。

我是C++模板編程領域的新手,上面的3個問題基本和簡單。我在谷歌搜索一些問題,但仍然不知道。所以我在這裏發佈我的問題。

+1

*「但是,爲什麼聲明和實現專業化模板類的應該在不同的代碼文件?「*顯式(完全)專用類模板的成員函數是*簡單函數*,也就是說,ODR適用於其他任何成員函數:程序中必須只有一個定義,如果它們不是'inline'。 – dyp

回答

2
  1. <T>可以從template <typename T> void mytest<T>::method(T input)中省略嗎?

    不可以。儘管在簡單情況下它似乎是多餘的,但在更復雜的情況下,例如當存在多個部分專業化時,它變得必要。保持語法一致也很有幫助。

  2. 當把一個完全專用的類模板的成員函數的定義放入頭部時,會出現「the」錯誤(我假設你得到了多重聲明的符號)。

    完全專用的類模板的成員函數被視爲非類模板的成員函數:只有一個版本,編譯器永遠不需要隱式地實例化它。因此,函數是而不是隱式內聯,就像它是任何函數模板的情況一樣,並且可能需要編譯器實例化。如果要將定義放入標題中,則需要明確聲明它爲inline

  3. 如何在類模板及其專業化之間共享函數?

    除了語法,類模板及其任何專業化沒有什麼共同之處。他們是完全獨立的班級。有兩種方法可以在不同專業領域之間共享通用功能:

    1. 將通用功能放入公共基類並實現其中的邏輯。如果功能需要訪問實際模板的成員,則可以使用curiously recurring template pattern爲基類授予專業化權限。
    2. 不要將通用功能設置爲成員函數,而是使其成爲接受任何專業化的功能模板。

    根據您的常用功能需要做什麼,其中一種或另一種方法效果更好。

+0

如果你想顯式地專門化一個類模板的某些成員函數,例如'template struct mytest {void common(){/*...*/} void special(){/ * ... * /}}; template <> void mytest :: special(){/*...*/}' – dyp

1

小除了迪特馬爾·庫爾的答案1.感覺不一樣:

template <class T> 
void mytest<T>::method(T input) 
{ 
    // ... 
    // use of input 
} 
  • 實現:

    • 非專業類模板template <class T> class mytest的方法的實現部分類模板專業化方法template <class T> class mytest<T*>指向對象的方法:

      template <class T> 
      void mytest<T*>::method(T* input) 
      { 
          // ... 
          // use of *input 
      } 
      
    • 局部類模板特template <class U, class V> class mytest<U V::*>的方法的執行情況的指針到另一個類的數據成員:

      void mytest<char>::method(char input) 
      { 
          // ... 
          // use of input 
      } 
      

      template <class U, class V> 
      void mytest<U V::*>::method(V& object, U V::* input) 
      { 
          // ... 
          // use of object.*input 
      } 
      
    • 完整的類模板特template <> class mytest<char>的方法的實施

    • 實現非專門化類模板的全部專用方法template <class T> class mytest<T>

      template <> 
      void mytest<int>::method(int input) 
      { 
          // ... 
          // use of input 
      }