c++模板、模板的全特化與偏特化
阿新 • • 發佈:2018-11-11
1. c++模板的一般使用方法
1. 類模板
#include<iostream> using namespace std; template <typename T> class MyClass { public: MyClass <T>(T a, T b) { this->a = a; this->b = b; } public: T GetA() { return this->a; } T GetB() { return this->b; } private: T a; T b; }; int main() { //MyClass mc; //錯誤,必須指定型別,因為要開闢空間 MyClass<int> mc(3, 4); cout << "mc.a:" << mc.GetA() << '\n' << "mc.b:" << mc.GetB() << endl; return 0; }
輸出結果:
我們再嘗試將成員函式在類外定義:
template <typename T>
class MyClass
{
public:
MyClass <T>(T a, T b)
{
this->a = a;
this->b = b;
}
public:
T GetA();
T GetB();
private:
T a;
T b;
};
T MyClass::GetA()
{
return this->a;
}
T MyClass::GetB()
{
return this->b;
}
如果以這種常規形式類外定義類成員,我們發現是無法通過編譯的:
第一個問題:T編譯器不認識了;
第二個問題:缺少類模板MyClass的引數列表
為了讓編譯器再次認識T,我們將template <typename T>拿到每個函式上面;然後在MyClass後面加上模板引數列表:
template <typename T>
T MyClass<T>::GetA()
{
return this->a;
}
template <typename T>
T MyClass<T>::GetB()
{
return this->b;
}
這樣程式就可以正常的運行了。
小結論:在類外定義模板類成員函式時,格式為:template<T> 返回值 類名<T>:: 函式名(){} ;
另外,在所有出現MyClass的地方都需要模板引數列表。
2. 函式模板
#include<iostream>
using namespace std;
template <typename T>
T Add(T a, T b)
{
return a + b;
}
int main()
{
cout << Add(1, 2) << endl;
return 0;
}
可以看到:呼叫Add時並沒有在Add後新增模板引數列表。
執行結果:
小結論:類模板不能自動推演模板的型別,而函式模板可以根據引數自動匹配。
2. c++類模板的全特化
#include<iostream>
using namespace std;
template <typename T1, typename T2>
class MyClass
{
public:
MyClass <T1, T2>(T1 a, T2 b)
{
this->a = a;
this->b = b;
}
public:
T1 GetA(){return this->a;}
T2 GetB(){return this->b;}
private:
T1 a;
T2 b;
};
//實現了MyClass的全特化
template <>
class MyClass<int, char>
{
public:
MyClass (int a, char b)
{
this->a = a;
this->b = b;
}
public:
int GetA(){return this->a;}
char GetB(){return this->b;}
private:
int a;
char b;
};
int main()
{
//MyClass mc; //錯誤,必須指定型別,因為要開闢空間
MyClass<int, char> mc(3, 'c');
cout << "mc.a:" << mc.GetA() << '\n' << "mc.b:" << mc.GetB() << endl;
return 0;
}
執行結果:
顯而易見,全特化的意思就是將原本模板的泛型引數全部變成了指定的型別。
3. c++類模板的偏特化
理解了全特化,偏特化就不難理解了:
template <typename T1, typename T2>
class MyClass
{
public:
MyClass <T1, T2>(T1 a, T2 b)
{
this->a = a;
this->b = b;
}
public:
T1 GetA(){return this->a;}
T2 GetB(){return this->b;}
private:
T1 a;
T2 b;
};
template <typename T2>
class MyClass<int, T2>
{
public:
MyClass (int a, T2 b)
{
this->a = a;
this->b = b;
}
public:
int GetA(){return this->a;}
T2 GetB(){return this->b;}
private:
int a;
T2 b;
};
可以看出,偏特化就是原本模板的泛型引數部分變成了指定的型別。
4. 三種類模板型別的呼叫優先順序
#include<iostream>
using namespace std;
template <typename T1, typename T2>
class MyClass
{
public:
MyClass(){}
public:
void WhoAmI()
{
cout << "I am general one" << endl;
}
};
template <>
class MyClass<int, char>
{
public:
MyClass(){}
public:
void WhoAmI()
{
cout << "I am complete one" << endl;
}
};
template <typename T2>
class MyClass<int, T2>
{
public:
MyClass(){}
public:
void WhoAmI()
{
cout << "I am incomplete one" << endl;
}
};
int main()
{
MyClass<int, char> mc1;
mc1.WhoAmI();
MyClass<int, double> mc2;
mc2.WhoAmI();
MyClass<char, double> mc3;
mc3.WhoAmI();
return 0;
}
執行結果:
小結論:對於三種類模板的呼叫優先順序從高到低為:全特化>偏特化>一般。