1. 程式人生 > >你所不知道的事兒--C++類模板的宣告和實現不能分離

你所不知道的事兒--C++類模板的宣告和實現不能分離

也許你具有良好的程式設計習慣,在定義一個類的時候總會把宣告和實現分離開,位於不同的檔案中。比如你定義一個類A,首先建立一個.h檔案,程式碼如下:

class A
{
public:
    A(int b);
    void show();
    ~A();
private:
    int a;
}

接下來你建立一個.cpp檔案實現類的宣告,程式碼如下:

#include"classA.h"
#include<iostream>
A::A(int b)
{
    a = b;
}

void A::show()
{
    std::cout << a << std::
endl; } A::~A() { }

接下來就要使用這個類了,新建一個cpp檔案,程式碼如下:

#inlucde"classA.h"
#include<iostream>
int main()
{
    A a(10);
    a.show();
    return 0;
}

可能你和我一樣,按照上訴程式設計習慣來寫類模板,這簡直就是個遭遇!
將上面的類A改為類模板,.h檔案如下:

template<class T>
class A
{
public:
    A(T b);
    void show();
    ~A();
private:
     T a;
}

把.cpp檔案改為如下:

#include"classA.h"
#include<iostream>
template<class T>
A<T>::A<T>(T b)
{
    a = b;
}

template<class T>
void A<T>::show()
{
    std::cout << a << std::endl;
}

template<class T>
A<T>::~A<T>()
{
}

main函式的.cpp檔案程式碼改為:

#inlucde"classA.h"
#include<iostream>
int main()
{
    A<int> a(10);
    a.show();
    return 0;
}

此時執行,錯誤發生。如果我們將類模板的宣告和定義寫在一個檔案中呢,即把.h和.cpp檔案合併,得到如下程式碼:

template<class T>
class A
{
public:
    A(T b);
    void show();
    ~A();
private:
     T a;
}

template<class T>
A<T>::A<T>(T b)
{
    a = b;
}

template<class T>
void A<T>::show()
{
    std::cout << a << std::endl;
}

template<class T>
A<T>::~A<T>()
{
}

這樣在進行除錯,則沒有錯誤。

所以,我們得到:
類模板不能將宣告和實現分離在兩個檔案中!!

但是究其原因:
《C++程式設計思想》中這麼說:模板定義很特殊。由template<…>處理的任何東西都意味著編譯器在當時不為它分配儲存空間,它一直處於等待狀態直到被一個模板例項告知。在編譯器和聯結器的某一處,有一機制能去掉指定模板的多重定義。所以為了容易使用,幾乎總是在標頭檔案中放置全部的模板宣告和定義