文章目錄
- 模版類
- 1. 模版類
- 2. 模版參數限制
- 3. 模版繼承
- 3.1 嚴格模式
- 3.2 自由模式
- 4. 模版類的模版函數
- 5. 返回值類型帶有模版
模版類
1. 模版類
#include <iostream>using namespace std;/*
當前 Person 類型,聲明了連個模版分別對應NameType 模版類型,名稱可以看出,用于約束成員變量 name 的類型AgeType 模版類型,名稱可以看出,用于約束成員變量 age 的類型模版類型充當數據類型占位符,在整個類中,成員變量,成員函數,構造函數都可以使用
*/
template <typename NameType, typename AgeType>
class Person
{
public:Person() {}Person(NameType name, AgeType age) : name(name), age(age) {}Person(const Person & person) : name(person.name), age(person.age) {}~Person() {}NameType getName() { return name; }void setName(NameType name) { this->name = name; }AgeType getAge() { return age; }void setAge(AgeType age) { this->age = age; }private:NameType name;AgeType age;
};int main(int argc, char const *argv[])
{/*Person 類型帶有模版修飾,需要在使用之前明確模版對應的具體類型模版具備數據類型支持的多樣性,同時一旦確定模版類型,嚴格遵守數據類型一致化原則Person 類型如何確定模版對應的具體數據類型格式:類名<模版對應具體數據類型> * 對象 = new 類型<模版對應具體數據類型>(...);Person<NameType, AgeType>*/// p1 明確告知編譯器 NameType ==> string AgeType ==> int// 在后續的代碼中,通過 p1 調用 Person 類內函數按照以上規則完成Person<string, int> *p1 = new Person<string, int>();p1->setName("布丁");p1->setAge(3);cout << "Name : " << p1->getName() << ", Age : " << p1->getAge() << endl;Person<string, int> *p2 = new Person<string, int>("張三", 14);cout << "Name : " << p2->getName() << ", Age : " << p2->getAge() << endl;delete p1;delete p2;return 0;
}
2. 模版參數限制
雙重限制
- 限制外部類型
- 限制模版類型
#include <iostream>using namespace std;template <typename DataType, typename MsgType>
class Data
{
public:Data() {}Data(DataType value, MsgType msg) : value(value), msg(msg) {}Data(const Data &data) : value(data.value), msg(data.msg) {}~Data() {}DataType getValue() { return value; }void setValue(DataType value) { this->value = value; }MsgType getMsg() { return msg; }void setMsg(MsgType msg) { this->msg = msg; }private:DataType value;MsgType msg;
};/*
當前 test1 函數明確告知調用者,當前所需的參數為 Data
同時限制 Data 中對應的模版類型為 <int, string>
*/
void test1(Data<int, string> *data);/*
當前 test1 函數明確告知調用者,當前所需的參數為 Data
同時限制 Data 中對應的模版類型為 <double, string>
*/
void test1(Data<double, string> *data);int main(int argc, char const *argv[])
{/*雙重限制*/Data<int, string> *d1 = new Data<int, string>(10, "別困!");Data<double, string> *d2 = new Data<double, string>(3.14, "別困!!");Data<char, string> *d3 = new Data<char, string>('G', "遵守數據類型一致化原則");test1(d1);test1(d2);/*test1 函數重載操作,所需函數有兩種情況Data<int, string> *Data<double, string> *并沒有支持Data<char, string> * 考慮到雙重限制,分別對應外部類型和模版類型因此 d3 無法作為函數 test1 的實際參數【注意】請遵守數據類型一致化原則*/// test1(d3);delete d1;delete d2;delete d3;return 0;
}void test1(Data<int, string> *data)
{cout << "value : " << data->getValue() << ", Msg : " << data->getMsg() << endl;
}void test1(Data<double, string> *data)
{cout << "value : " << data->getValue() << ", Msg : " << data->getMsg() << endl;
}
3. 模版繼承
3.1 嚴格模式
#include <iostream>using namespace std;/*
類帶有模版,同時有子類繼承當前類1. 自由模式子類帶有和父類同名聲明模版2. 嚴格模式【當前模式】子類在繼承父類時,直接指定模版的具體類型,不得修改
*//*
MyCompare 類1. 聲明了模版2. 聲明純虛函數3. MyCompare 是一個抽象類
*/
template <typename T>
class MyCompare
{
public:// 純虛函數,并且使用了類聲明的模版virtual bool compare(T t1, T t2) = 0;
};
/*
IntCompare 類1. 繼承了 MyCompare 抽象類2. 繼承父類的過程中,同時限制了模版對應的具體類型3. IntCompare 類沒有聲明模版IntCompare 目標是一個【實現類】1. 必須實現 Compare 函數2. 父類 MyCompare 已經明確限制模版對應的具體類型為 int 類型3. IntCompare 目標實現的函數bool compare(int t1, int t2)
*/
class IntCompare : public MyCompare<int>
{
public:bool compare(int t1, int t2){return t1 > t2;}
};int main(int argc, char const *argv[])
{/*bool compare(long t1, long t2) {...}在明確 模版對應的類型為 int 類型,實現上面的函數實例化的過程中,會出現報錯:純虛擬 函數 "MyCompare<T>::compare [其中 T=int]" 沒有強制替代項*/IntCompare * ic = new IntCompare;cout << "ret : " << ic->compare(30, 20) << endl; // 1cout << "ret : " << ic->compare(10, 20) << endl; // 0return 0;
}
3.2 自由模式
#include <iostream>using namespace std;/*
類帶有模版,同時有子類繼承當前類1. 自由模式【當前模式】子類帶有和父類同名聲明模版2. 妻管嚴模式子類在繼承父類時,直接指定模版的具體類型,不得修改
*//*
MyCompare 類1. 聲明了模版2. 聲明純虛函數3. MyCompare 是一個抽象類
*/
template <typename T>
class BaseHandler
{
public:// 純虛函數,并且使用了類名聲明的模版virtual void handler(T t) = 0;
};/*
MyHander 繼承抽象類 BaseHandler,同時1. 聲明和 BaseHandler 同名模版2. 當前模版類型尚未明確3. 必須實現 void hander(T t) 函數
*/
template <typename T>
class MyHandler : public BaseHandler<T>
{
public:void handler(T t){cout << "數據情況 : " << t << endl;}
};int main(int argc, char const *argv[])
{// 實例化 MyHandler 類對象,需要指定模版對應的具體類型MyHandler<string> * m1 = new MyHandler<string>;m1->handler("零零零零");MyHandler<int> * m2 = new MyHandler<int>;m2->handler(14);delete m1;delete m2;return 0;
}
4. 模版類的模版函數
#include <iostream>using namespace std;template <typename T>
class Test
{
public:// 當前函數使用的模版為當前 Test 類聲明的模版void handler(T t) { cout << "value : " << t << endl; }/*模版類內的函數,期望可以自定義模版,使用的模版數據形式,約束與當前類不同*/template <typename T2>void my(T2 t) { cout << "value : " << t << endl; }
};int main(int argc, char const *argv[])
{Test<string> * test = new Test<string>;test->handler("零零零零");/*my 函數對應的模版類型,由實際參數決定,并不是實例化 Test 類型決定*/test->my(3.14);return 0;
}
5. 返回值類型帶有模版
#include <iostream>using namespace std;/*
K ==> Key 鍵
V ==> Value 值
*/
template <typename K, typename V>
class Data
{
public:Data() {}Data(K key, V value) : key(key), value(value) {}Data(const Data & data) : key(data.key), value(data.value) {}~Data() {}K getKey() { return key; }void setKey(K key) { this->key = key; }V getValue() { return value; }void setValue(V value) { this->value = value; }/*友元函數中,重載運算符操作,使用的模版并不是 Data 聲明的模版而是函數自定義模版,通過實際參數 Data 類型中的模版情況,限制當前函數的模版類型【滿足注意 Data 類型展示數據操作】*/template <typename K1, typename V1>friend ostream & operator<<(ostream & o, Data<K1, V1> * data);private:K key;V value;
};template <typename K1, typename V1>
ostream & operator<<(ostream & o, Data<K1, V1> * data)
{o << "Key : " << data->getKey() << ", Value : " << data->getValue();return o;
}template <typename K, typename V>
Data<K, V> *getData(K key, V value);int main(int argc, char const *argv[])
{string name = "MY";Data<string, int> * data = getData(name, 3);cout << data << endl;Data<double, int> * data1 = getData(6.18, 9999);cout << data1 << endl;delete data;delete data1;return 0;
}/*
外部函數自定義模版,返回值是 Data 類型,同時
利用當前函數的實際參數對 Data 中模版數據進行
約束限制,模版具體數據情況根據參數具體數據類型確定!
*/
template <typename K, typename V>
Data<K, V> * getData(K key, V value)
{return new Data<K, V>(key, value);
}