模版类
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. 模版参数限制
双重限制文章来源地址https://www.toymoban.com/news/detail-835401.html
- 限制外部类型
- 限制模版类型
#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; // 1
cout << "ret : " << ic->compare(10, 20) << endl; // 0
return 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);
}
文章来源:https://www.toymoban.com/news/detail-835401.html
到了这里,关于C++(12) 模板类、模板继承(严格模式和自由模式)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!