你所不知道的事兒--C++類模板的宣告和實現不能分離
阿新 • • 發佈:2019-01-29
也許你具有良好的程式設計習慣,在定義一個類的時候總會把宣告和實現分離開,位於不同的檔案中。比如你定義一個類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<…>處理的任何東西都意味著編譯器在當時不為它分配儲存空間,它一直處於等待狀態直到被一個模板例項告知。在編譯器和聯結器的某一處,有一機制能去掉指定模板的多重定義。所以為了容易使用,幾乎總是在標頭檔案中放置全部的模板宣告和定義。