前言
在分析STL
之前, 我們需要先對template
做一個回憶, 可能我總結的內容你都會了, 也可能你沒有了印象了, 但是我還是希望你先瀏覽一下template的用法. 畢竟STL全部都涉及到了模板, 而template是學習STL的基礎.
template使用
template
的使用大大提高了代碼的複用性, 抽象性.
- 類模板實例化時並不是每個成員函數都實例化了, 而是使用到了哪個成員函數, 那個成員函數才實例化.
/* ***** 1 *******/
template<class T>
class point
{
public:
point() : x(0), y(0) {}
point(T x, T y) : x(x), y(y) {}
T getX() const { x = y; return x; } // 一般是無法通過編譯的, x不允許被修改, 但是這裏並沒有報錯
private:
T x;
T y;
};
/* ***** 2 *******/
#define T int
class point
{
public:
point() : x(0), y(0) {}
point(T x, T y) : x(x), y(y) {}
T getX() const { x = y; return x; }
private:
T x; T y;
};
成員函數getX()應該無法通過編譯, 就像實例2一樣, 但是因爲模板中沒有使用到函數getX(), 也就沒有實例化getX, 所以就沒有出現編譯報錯. 實例2必須在編譯的時候就要檢查所有的成員即函數.
不是所有的模板都只能在運行時纔會被實例化, 比如非類型模板參數就能在編譯時期就已經實例化了, 這裏主要說的是類模板, 不要混淆了.
- 可以把類模板和函數模板結合起來, 定義一個含有成員函數模板的類模板.
template<class T>
class point
{
public:
point() : x(0), y(0) {}
point(T x, T y) : x(x), y(y) {}
template<class U> // 定義了另一個的模板參數類型
void print(U x);
private:
T x;
T y;
};
// 這裏兩個都要寫出來
template<class T>
template<class U>
void point<T>::print(U x)
{
std::cout << this->x + x;
}
int main()
{
point<int> p;
p.print(3.14); // 因爲是模板函數, 所以交給編譯器自行推導
exit(0);
}
- 類模板中可以聲明static成員, 在類外定義的時候要增加template相關的關鍵詞, 並且需要注意每個不同的模板實例都會有一個獨有的static成員對象.
template<class T>
class tmp
{
public:
static T t;
};
template<class T>
T tmp<T>::t = 0;
int main()
{
tmp<int> t1;
tmp<int> t2;
tmp<double> t3;
t1.t = 1;
std::cout << "t1.t = " << t1.t << endl;
std::cout << "t2.t = " << t2.t << endl;
cout << "t3.t = " << t3.t << endl;
exit(0);
}
輸出結果:
t1.t = 1
t2.t = 1
t3.t = 0
模板中的static
是在每個不同的類型實例化一個, 相同類型的實例化對象共享同一個參數. 所以這裏的t1, t2中哦t都是同一個實例化變量, 是共享的.
總結
本節只是簡單講了template
在實例化時期和使用static, 嵌套模板的使用和注意, 下一節着重分析template的非類型參數.