前提
我们先来看一类问题,如下的三个方法能否换成一个方法呢?
这就是模版的来历。
int funcadd(int a, int b) {
return a + b;
}
double funcadd(double a, double b) {
return a + b;
}
float funcadd(float a,float b) {
return a + b;
}
模版的概念
所谓泛型编程,是以独立于 任何 特定类型的方式编写代码
这意味着,我们在声明或者定义的时候,不会指定具体的类型。
但是在使用的时候,需要指定具体的类型或者值
模版是泛型编程的基础公式。
模版一般分为 函数模版 和 类模版
函数模版定义:
template <class T1,class T2>
T1 func88(T1 a, T2 b) {
return a + b;
}
函数模版的定义通常都是在.h文件中
函数模版的调用
int a =10; int b =20;
func88(a,b);
函数模版 的常用方式一:
定义的时候:使用 如下的代码,告知C++编译器:"T 是一种类型,不要报错".
在编译阶段:当编译器看到有函数模版的具体调用的时候,函数模版才会生成具体的函数;
如果没有调用,编译器则不会生成具体的函数;
template <typename T>
或者
template <class T>
函数模版
//如上的三个函数,能写成一个函数会更好,这就是模版存在的意义。
template <class T>
T funcadd(T a, T b) {
return a + b;
}
void main() {
int a = 1;
int b = 2;
cout << funcadd<int>(a ,b) << endl;
double a1 = 9.9;
double b1 = 89.9;
cout << funcadd(a1, b1) << endl;
}
template <class T1,class T2>
T1 func88(T1 a, T2 b) {
return a + b;
}
使用:
int a2 = 10;
double b2 = 89.8;
int a3 = func88(a2,b2);
cout << a3 << endl;
int a4 = 1000;
int a5 = func88(a2, a4);//T1 和 T2 可以一样
cout << a5 << endl;
函数模版的不常用方式二:
直接在template 上定义了具体的类型。
template<int a1 , int a2>
int func89(){
return a1 + a2;
}
template<int a1 , int a2>
int func89(){
return a1 + a2;
}
void main() {
cout<<func89<10, 20>()<<endl;
int aa = 10;
//cout << func89<aa, 20>() << endl;//会有build error。这里其实没有理解,理论上应该知道是啥类型才对
}
类模版定义:
类模版的定义通常都是在.h文件中,
且必须要有类的全部信息 --- 包括类模版中的成员函数的函数体。文章来源:https://www.toymoban.com/news/detail-782616.html
和函数模版一样,编译器在实例化模版类时候,编译器就会生成一个具体的类文章来源地址https://www.toymoban.com/news/detail-782616.html
//类模版
template <class T, class T1>
class Teacher89 {
typedef T1* myiterator;
public :
T m_age;
myiterator iter;//迭代器
public:
Teacher89() {
cout << "空的 构造函数" << endl;
}
Teacher89(T age, T1 iter):m_age(age){
cout << "有两个参数的 构造函数" << endl;
this->iter = &iter;
}
//类模版中的成员函数 函数体 写在类模版中,会被声明为inline函数,
int getInt() {
return 10;
}
//类模版中的成员函数 函数体 写在类模版外,只是在类模版中声明
double getdouble();
//类模版中成员函数如果返回值是 一个模版类行,函数体写在类模版外,只是在类模版中声明
myiterator getInterator();
//注意的是:即使实例化模版之后,如果没有任何成员函数被使用,类模版中的成员函数也不会被实例化。
//但是当只要有一个 成员函数被使用,那么所有的类成员函数模版都会被实例化
};
template <class T, class T1>
double Teacher89<T, T1>::getdouble() {
return 89.9;
}
template<typename T, class T1> //typename Teacher89<T, T1 >::myiterator 声明这玩意是个返回类型
typename Teacher89<T, T1 >::myiterator Teacher89<T, T1>::getInterator(){
return Teacher89<T, T1>::iter;
}
void main() {
cout << "断点" << endl;
Teacher89<int, string *> t89; //模版类的实例化
//注意的是:Teacher89是类的模版名,Teacher89<int, string *>才是类型名。
//所以,一个实例化的类型,总会用尖括号<>包含着模版参数
string abc("nihao");
Teacher89<int, string > t891(80,abc);//模版类的实例化
cout << t891.getInt() << endl;
cout << t891.getdouble() << endl;
cout << t891.getInterator() << endl; // 打印出来的是地址:0x00000077676ffbb8,debug看到在构造函数中 :this->iter = 0x00000077676ffbb8 "nihao"
cout << "---" << endl;
cout << *(t891.getInterator()) << endl; //但是这个打印不出来nihao,啥都打印不出来,原因未知???
}
到了这里,关于31 C++ 模版和泛型的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!