当前位置:首页 » 《随便一记》 » 正文

植物大战 模板——C++

20 人参与  2022年10月01日 08:51  分类 : 《随便一记》  评论

点击全文阅读


“”

猛戳订阅?? ? [C++详解专栏] ? ??

这里是目录

一、泛型编程二、函数模板1.函数模板的实例化 三、类模板1.类模板的定义格式 四、非类型模板参数五、模板的特化1.函数模板的特化2.类模板的特化全特化偏特化 六、模板分离编译(重点)1.什么是分离编译 ?2.模板的声明和定义3.模板的分离编译原理 为什么分离就链接不上?

一、泛型编程

概念
编写与类型无关的通用代码,达成代码复用,模板是泛型编程的基础

模板就是把工作交给编译器去做。让编译器去生成多个函数,省的我们再去写函数模板。比如Add加法函数。

平时经常用的是函数模板和类模板

二、函数模板

函数模板格式:

template<typename T1,typename T2,typename T3.....>

这里需要有个感性的认知:

1.一个模板参数只能定义一个函数。模板参数可以有缺省参数。

2.模板参数是类型函数参数是对象
模板参数传递的是类型,函数参数传递的是对象值

3.普通函数是有地址的,而模板函数没有地址。
但是模板会推算,会通过实参传递给形参,推算他的实际类型

template<typename T>void Swap(T& left, T& right){T temp = left;left = right;right = temp;}

1.函数模板的实例化

实例化:用不同类型的参数使用函数模板时,称为函数模板的实例化
但是有时候也有例外。需要显式实例化。
代码如下

template<class T>T* func(int n){return new T[n];}int main(){int* p = func<int>(10);return 0;}

typename是用来定义模板参数的关键字。也可以用class.但是不能用struct

三、类模板

1.类模板和函数模板不同。函数模板一般可以显式传参推出实际类型。

2.而类模板不能传参推断类型,所以类模板需要在类名的 后面加尖括号<>里面加类型,这叫做类模板的显式实例化

例如:

vector<int> v1;//int类型vector<double> v2;//元素是double类型

1.类模板的定义格式

注意:
cao不是具体的一个类,而是编译器根据被实例化的类型生成具体类的模具。

template<class T1, class T2>class 类模板名{//类内成员定义};//类模板template<class T>class cao{};//类模板的实例化cao<int> c;//cao类名,cao<int>才是类型

四、非类型模板参数

概念:非类型形参。就是用一个常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用

1.非类型的模板参数无法修改
2.浮点数,类对象以及字符串无法做非类型模板参数
(非类型模板参数一般是整形)
3.非类型的模板参数必须在编译期间就能确认结果。

N就是非类型形参。

template<class T, size_t N = 10>

五、模板的特化

使用模板可以实现与类型无关的代码。但有时候还需要做一些特殊处理。

1.函数模板的特化

特化步骤
1.必须要先有一个基础的函数模板
2.关键字template后面接一对空的尖括号<>
3.函数名后跟一对尖括号,尖括号中指定需要特化的类型。
4.函数形参表:必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪错误

struct Date{int _year = 1;int _month = 1;int _day = 1;};//基础的函数模板template<class T>bool IsEqual(T left, T right){return left == right;}//关键字template后面接一对空的尖括号<>template<>//函数名后跟一对尖括号,尖括号中指定需要特化的类型//函数形参表:必须要和模板函数的基础参数类型完全相同bool IsEqual<Date*>(Date* left, Date* right){return left->_year == right->_year&& left->_month == right->_month&& left->_day == right->_day;}int main(){cout << IsEqual(1, 2) << endl;Date* p1 = new Date;Date* p2 = new Date;cout << IsEqual(p1, p2) << endl;return 0;}

2.类模板的特化

全特化

全特化就指的是模板参数列表中所有的参数都确定化

//全特化template<class T1, class T2>class Data{public:Data(){cout << "Data<T1, T2>" << endl;}private:T1 _d1;T2 _d2;};//跟一对尖括号<>template<>class Data<int, char>{public:Data(){cout << "Data<int,char>" << endl;}private:int _d1;char _d2;};int main(){Data<int, int> d1;//模板的全特化Data<int, char> d2;}

偏特化

偏特化是针对模板参数进一步进行条件限制设计的特化版本。

//类的基础模板template<class T1, class T2>class Data{public:Data(){cout << "Data<T1, T2>" << endl;}private:T1 _d1;T2 _d2;};//1.部分特化//将模板参数列表中的一部分参数特化。template <class T1>class Data<T1, int>{public:Data(){cout << "Data<T1, int>" << endl;}private:T1 _d1;int _d2;};//两个参数偏特化为引用类型template <typename T1, typename T2>class Data <T1*, T2*>{public:Data() { cout << "Data<T1*, T2*>" << endl; }private:T1 _d1;T2 _d2;};//两个参数偏特化为引用类型template <typename T1, typename T2>class Data <T1&, T2&>{public:Data(const T1& d1, const T2& d2):_d1(d1), _d2(d2){cout << "Data<T1&, T2&>" << endl;}private:const T1& _d1;const T2& _d2;};int main(){Data<double, int> d1;Data<int, double> d2;Data<int*, int*> d3;Data<int&, int&> d4(1,2);}

六、模板分离编译(重点)

1.什么是分离编译 ?

一个程序由若干个源文件组成。而每个源文件单独编译成目标文件,然后目标文件链接起来形成可执行文件的过程称为分离编译。

模板一般不支持分离编译。但普通函数是可以的。

C/C++程序要运行,基本步骤.
预处理 -> 编译->汇编->链接

2.模板的声明和定义

函数模板的声明和定义也有一些讲就。
声明:

template<typename T>void Swap(T& left, T& right);

定义:

template<typename T>void Swap(T& left, T& right){T temp = left;left = right;right = temp;}

注意:类模板的定义还需要加上类域。

3.模板的分离编译原理

a.cpp
在这里插入图片描述
a.h
在这里插入图片描述
main.cpp
在这里插入图片描述

a.h头文件不参与编译。
a.cpp中不会生成模板函数的实例化,
main.cpp中调用函数链接时找地址。main.cpp包含的头文件只有a.h的。但是a.cpp中没有实例化所以没有地址。

解决方法
1.将声明和定义放到一个文件.hpp的文件中。
2.模板定义的位置显式实例化。(不推荐使用).

模板的优点:

1.模板复用了代码,节省了资源。STL标准模板库因此而产生。
2.增强了代码的灵活性。

缺点:
1.模板会导致代码膨胀,也会导致编译时间变长。
2.出现模板编译错误时,错误信息非常凌乱,不易定位错误

为什么分离就链接不上?

符号表找不到。
和实例化有关系。

a.cpp 从预处理到 a.i经过了头文件的展开
a.i经编译到a.s再经过汇编到a.o什么都没干,因为模板的类型没有确定,所以没法实例化。a.s和a.o都是空的,空壳子。

解决办法:
1.显示实例化,太矬了,几乎不用这个办法。
2.不分离到两个文件中,放到同一个文件中。这样为什么就可以了呢?
为什么就不存在链接错误了?**原因是因为在main.cpp中头文件展开后,有了函数模板的声明和定义。**在链接的时候就不用找他的地址了。


点击全文阅读


本文链接:http://zhangshiyu.com/post/45164.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1