电子商务网站建设与管理的实践报告,wordpress媒体库显示不出来,ps制作网站首页教程,趣头条自媒体平台注册✨ Blog’s 主页: 白乐天_ξ( ✿#xff1e;◡❛)
#x1f308; 个人Motto#xff1a;他强任他强#xff0c;清风拂山岗#xff01;
#x1f4ab; 欢迎来到我的学习笔记#xff01;
本文参考博客#xff1a;一同感受C模版的所带来的魅力
一、泛型编程思想
首先… ✨ Blog’s 主页: 白乐天_ξ( ✿◡❛) 个人Motto他强任他强清风拂山岗 欢迎来到我的学习笔记
本文参考博客一同感受C模版的所带来的魅力
一、泛型编程思想
首先我们来实现一个swap交换函数。如果学过了C的函数重载和引用的话就可以写出swap函数不同参数类型的重载函数。注意C语言中不支持重名函数的
void Swap(int left, int right)
{int temp left;left right;right temp;
}
void Swap(double left, double right)
{double temp left;left right;right temp;
}
void Swap(char left, char right)
{char temp left;left right;right temp;
} 根据上面的代码我们就可以感觉到swap交换函数仅仅只是实现一个交换功能却需要根据参数的类型写出几个很相似的函数重复相同或者相近的代码。如果又增加了其他类型数据需要进行交换呢继续重复相同的操作再去实现这个函数吗 这样操作虽然可行但是它存在几处缺陷
重载的函数仅仅只是类型不同代码复用吕比较低只要有新的类型出现就需要自己再次实现所需类型的相近函数。代码的可维护性比较低一个出错可能所有的重载均出错。
那么既然重载函数的重复率比较高能否只给出一个标准然后让他们自己根据这个标准去实现所需要的东西呢
这个标准就像做月饼用的模具一样我们只需要放入材料就可以利用模具做出形状相同的月饼。 后来C就生成一个类似于模具的东西将其交给编译器让编译器根据这个模具自行生成所需代码。这就是泛型编程思想编写与类型无关的通用代码是代码复用的一种手段。模板是泛型编程的基础。
二、函数模板–函数的模板
2.1 概念 函数模板代表了一个函数家族该函数模板与类型无关在使用时被参数化根据实参类型产生函数的特定类型版本。 通过函数模板可以编写一种通用的函数定义使其能够是用于多种数据类型从而提高代码的服用行和灵活性。
2.2 格式
声明一个函数模板需要关键字template内部是模板参数可以使用class或者typename来进行类型的声明不能用struct。然后开始使用模板参数Tn
templatetypename T1,typename T2,typename T3,……,typename Tn
返回值类型 函数名参数列表
{ }注意这里的函数模板的参数和普通的函数参数不一样。函数模板参数定义的是u类型/u而普通函数参数定义的是u对象/u。
返回值类型 函数名(参数列表){ }在了解上面的函数模板后我们就可以为Swap()函数写一个通用的函数模板了。
//模板类型
templatetypename T
void Swap(T left, T right)
{T temp left;left right;right temp;
}运用
int main()
{int a1 10, a2 20;double d1 1.1, d2 2.2;cout a1: a1 a2: a2 endl;cout d1: d1 d2: d2 endl;Swap(a1, a2);swap(d1, d2);cout a1: a1 a2: a2 endl;cout d1: d1 d2: d2 endl;return 0;
}运行结果 调试就可以发现Swap函数的函数模板可以自己推导传入参数的类型。 那如果给是Swap函数传入不同的参数类型呢
//模板类型
templatetypename T
void Swap(T left, T right)
{T temp left;left right;right temp;
}templateclass T1,class T2
void func(const T1 x,const T2 y)//不同的类类型
{ }
int main()
{int a1 10, a2 20;double d1 1.1, d2 2.2;//传入不同的类型Swap(a1, d1); //error message : “void Swap(T ,T )”: 模板 参数“T”不明确// message : 可能是“double”或 “int”//message: “void Swap(T, T)” : 无法从“double”推导出“T ”的 模板 参数func(a1, d1); //rightreturn 0;
}message : “void Swap(T ,T )”: 无法从“double”推导出“T ”的 模板参数 那为什么func()函数传入不同的类型的参数却没有问题呢 原因传入func()函数的参数并没有用来做编译器无法推导参数类型的操作。Swap()函数是因为编译器无法推导出参数类型。一个T类型结果参数是两个类型 其实在C中早就已经定义好了swap()这个函数头文件utility我们可以直接使用。 2.3 原理
2.4 实例化
用不同类型的参数使用函数模板称为函数模板的实例化。现在我们利用下面这个函数模板来理解实例化概念。
//用函数模板生成对应的函数--模板的实例化
templateclass T//一个模板参数T
T Add(const T left, const T right)
{return left right;
}2.4.1 隐式实例化
概念
隐式实例化推导实例化让编译器根据实参推演模板参数的实际类型再返回不同类型的数据。
int main()
{int a1 10, a2 20;double d1 10.1, d2 20.2;//推导实例化实参传递给形参编译器推导出T的类型cout Add(a1, a2) endl;cout Add(d1, d1) endl;return 0;
}运行结果 缺陷传入参数类型不同编译器左右为难、骑虎难下。
int main()
{int a1 10, a2 20;double d1 10.1, d2 20.2;cout Add(a1, d1) endl;//message : “T Add(const T ,const T )”: 无法从“double”推导出“const T ”的 模板 参数return 0;
}①d1强制类型转换为int类型解决类型冲突问题。
cout Add(a1, (int)d1) endl;②a1强制类型转换为double类型解决类型冲突问题。
cout Add((double)a1, d1) endl;③ 如果非要传入不同类型的参数就应该用不同的模板参数重新定义一个函数模板。
templateclass T1 left,class T2 right
T1 Add(const T1 left,const T2 right)//两个模板参数
{return left right;
}2.4.2 显示实例化
概念
显示实例化在函数名后面紧跟并在其中指定模板参数的实际类型。
//显示实例化用指定类型来实例化
cout Addint(a1, d1) endl;
cout Adddouble(a1, d1) endl;缺陷其实在某些场景下面我们只能选择显示实例化。
形参部分不是模板参数而是普通的自定义类型返回值才是。此时我们无法通过传参来指定这个T的类型只有外部在调用这个模板时显示指定。
templateclass T
T* Alloc(int n)
{return new T[n];
}
// 有些函数无法自动推只能显示实例化
int main()
{// 有些函数无法自动推只能显示实例化double* p1 Allocdouble(10);float* p1 Allocfloat(20);int* p2 Allocint(30);return 0;
}2.5 模板参数的匹配原则
一个非模板函数可以和一个同名的函数模板同时存在而且该函数模板还可以被实例化为这个非模板函数。
//普通函数
int Add(int left, int right)
{return left right;
}
//函数模板
templateclass T
T Add(T left, T right)
{return left right;
}
int main()
{Add(1, 2);//调用了普通传参的函数Addint(1, 2);//调用了模板函数让其实生成对应的函数return 0;
}根据调试可以发现普通函数和函数模板是可以共存的。在进行普通传参时调用的是普通函数显示指定了类型时就会调用函数模板生成对应的函数。
对于非模板函数和同名函数模板如果其他条件相同在调用时会优先调用非模板函数而不会从该模板产生一个实例。如果模板可以产生一个更好匹配的函数那么将会选择模板。
// 普通函数
int Add(int left, int right)
{return left right;
}// 函数模板
templateclass T1, class T2
T1 Add(T1 left, T2 right)
{return left right;
}int main()
{Add(1, 2);//调用普通函数因为参数匹配Add(1, 2.2);///调用函数模板因为参数不匹配普通函数不接收此参数。//函数模板可以根据这个类型自动推导return 0;
}模板函数不允许自动类型转换但是普通函数可以进行自动类型转换。
普通函数传入的参数可以发生隐式类型转换又称【自动类型转换】下面代码中浮点数自动类型转换为整型数。
// 普通函数允许自动类型转换
void print(int value)
{std::cout Integer: value std::endl;
}int main()
{print(3); print(3.14); // 在这里发生了隐式类型转换浮点数自动类型转换为整型数return 0;
}对于函数模板来说是不能进行自动类型转换的。a和b是两个不同的类型并没有发生自动类型转换一个模板参数T就使得编译器无法进行自动推导。解决办法就是上面提到的隐式/显示类型转换。第三种方法就是增加模板参数。
template class T
void print(T a, T b) {cout a b endl;
}
int main()
{int a 1;double b 1.11;print(a, b);//error---message : “void print(T,T)”: 模板 参数“T”不明确return 0;
}
三、类模板–类的模板
3.1 类模板的定义格式
函数模板是加在函数上类模板是加在类上。
templateclass T1, class T2, ..., class Tn
class 类模板名
{// 类内成员定义
};类模板都是显示实例化。
templateclass T
class Stack
{
public:Stack(int n 4)//写构造:_array(new T[n])//不用检查是否失败失败了直接抛异常,_size(0),_capacity(n){}~Stack(){delete[] _array;_size _capacity 0;_array nullptr;}void Push(const T x)//传引用传参避免多余拷贝浪费资源能用引用就尽量使用引用{//空间不够用扩容if (_size _capacity){//不能使用realloc无构造//C无自动扩容的概念扩容需要手动T* temp new T[_capacity * 2];//扩容两倍size不变memcpy(temp, _array, sizeof(T) * _size);//拷贝数据delete[] _array;//delete一次即可释放旧空间_array temp;//指向新空间_capacity * 2;}_array[_size] x;}
//其他功能…………
private:T* _array;size_t _capacity;size_t _size;
};
int main()
{//类模板都是显示实例化Stackint st1;// intst1.Push(1);st1.Push(2);st1.Push(3);Stackdouble st2;// doublest2.Push(1.1);st2.Push(2.2);st2.Push(3.3);return 0;
}我们在C语言中学习栈的时候就有一个typedef的操作功能类似于这里的模板。既然如此那类模板的意义是什么呢 C语言中的栈只能实现某一种类型而C可以一个栈存入int类型另一个栈存入double类型。 就像在这里一样实现的栈的结构基本都是一样的不一样的只是存入栈的数据类型是不一样的。 如果在这里进行声明和定义的分离 定义的函数模板只能给当前的函数或者当前的类使用每个函数模板都需要定义自己的模板参数按需定义。当进行声明和定义分离时需要在函数前面单独声明类模板并指定类域。下面就是类模板中的成员函数在类外面实现所需要变化成的模板函数。
templateclass T
class Stack
{
public:Stack(int n 4):_array(new T[n]), _size(0), _capacity(n){}~Stack(){delete[] _array;_size _capacity 0;_array nullptr;}void Push(const T x);//其他功能……
private:T* _array;size_t _capacity;size_t _size;
};
//指定类域不行还需要声明一下类模板
templateclass T
void StackT::Push(const T x)//传引用传参避免多余拷贝浪费资源能用引用就尽量使用引用
{//空间不够用扩容if (_size _capacity){T* temp new T[_capacity * 2];memcpy(temp, _array, sizeof(T) * _size);delete[] _array;_array temp;_capacity * 2;}_array[_size] x;
}如果我们将上面分离后新声明的T改为X能否编译 能的。T只是一个符号而已我们实际上在调用这个函数时并没有T或者X的概念。 注意模板不支持声明和定义分离到两个不同文件中去。即使可以也相当繁琐。
3.2 类模板的实例化
类模板实例化和函数模板实例化不同。类模板实例化需要在类模板名称后面跟。然后将实例化的类型放在中即可类模板名字不是真正的类而实例化的结果才是真正的类。
int main()
{//类模板都是显示实例化Stackint st1;// intst1.Push(1);st1.Push(2);st1.Push(3);Stackdouble st2;// doublest2.Push(1.1);st2.Push(2.2);st2.Push(3.3);return 0;
}以上就是本文所要介绍的所有类容感谢您的阅读 文章转载自: http://www.morning.jxfmn.cn.gov.cn.jxfmn.cn http://www.morning.spqbp.cn.gov.cn.spqbp.cn http://www.morning.wrbx.cn.gov.cn.wrbx.cn http://www.morning.tnhqr.cn.gov.cn.tnhqr.cn http://www.morning.lqjpb.cn.gov.cn.lqjpb.cn http://www.morning.hnkkf.cn.gov.cn.hnkkf.cn http://www.morning.xmttd.cn.gov.cn.xmttd.cn http://www.morning.wptrm.cn.gov.cn.wptrm.cn http://www.morning.cbndj.cn.gov.cn.cbndj.cn http://www.morning.mprky.cn.gov.cn.mprky.cn http://www.morning.cnkrd.cn.gov.cn.cnkrd.cn http://www.morning.brwwr.cn.gov.cn.brwwr.cn http://www.morning.mhdwp.cn.gov.cn.mhdwp.cn http://www.morning.djlxz.cn.gov.cn.djlxz.cn http://www.morning.dhyqg.cn.gov.cn.dhyqg.cn http://www.morning.njstzsh.com.gov.cn.njstzsh.com http://www.morning.krswn.cn.gov.cn.krswn.cn http://www.morning.xbmwm.cn.gov.cn.xbmwm.cn http://www.morning.hpprx.cn.gov.cn.hpprx.cn http://www.morning.drwpn.cn.gov.cn.drwpn.cn http://www.morning.yfrbn.cn.gov.cn.yfrbn.cn http://www.morning.drywd.cn.gov.cn.drywd.cn http://www.morning.zzfqn.cn.gov.cn.zzfqn.cn http://www.morning.yqkmd.cn.gov.cn.yqkmd.cn http://www.morning.sblgt.cn.gov.cn.sblgt.cn http://www.morning.rttp.cn.gov.cn.rttp.cn http://www.morning.fhyhr.cn.gov.cn.fhyhr.cn http://www.morning.jpdbj.cn.gov.cn.jpdbj.cn http://www.morning.xqtqm.cn.gov.cn.xqtqm.cn http://www.morning.bpkqd.cn.gov.cn.bpkqd.cn http://www.morning.mtrz.cn.gov.cn.mtrz.cn http://www.morning.paoers.com.gov.cn.paoers.com http://www.morning.hxbjt.cn.gov.cn.hxbjt.cn http://www.morning.hyhzt.cn.gov.cn.hyhzt.cn http://www.morning.taipinghl.cn.gov.cn.taipinghl.cn http://www.morning.rlns.cn.gov.cn.rlns.cn http://www.morning.yzxhk.cn.gov.cn.yzxhk.cn http://www.morning.jwqqd.cn.gov.cn.jwqqd.cn http://www.morning.lqqqh.cn.gov.cn.lqqqh.cn http://www.morning.wynnb.cn.gov.cn.wynnb.cn http://www.morning.tkxr.cn.gov.cn.tkxr.cn http://www.morning.hwsgk.cn.gov.cn.hwsgk.cn http://www.morning.djgrg.cn.gov.cn.djgrg.cn http://www.morning.nbiotank.com.gov.cn.nbiotank.com http://www.morning.djgrg.cn.gov.cn.djgrg.cn http://www.morning.srbfz.cn.gov.cn.srbfz.cn http://www.morning.ssqwr.cn.gov.cn.ssqwr.cn http://www.morning.mkxxk.cn.gov.cn.mkxxk.cn http://www.morning.xsbhg.cn.gov.cn.xsbhg.cn http://www.morning.tqldj.cn.gov.cn.tqldj.cn http://www.morning.spghj.cn.gov.cn.spghj.cn http://www.morning.brwwr.cn.gov.cn.brwwr.cn http://www.morning.cxlys.cn.gov.cn.cxlys.cn http://www.morning.pswqx.cn.gov.cn.pswqx.cn http://www.morning.ngkng.cn.gov.cn.ngkng.cn http://www.morning.qwpyf.cn.gov.cn.qwpyf.cn http://www.morning.pxlql.cn.gov.cn.pxlql.cn http://www.morning.lbzgt.cn.gov.cn.lbzgt.cn http://www.morning.kdtdh.cn.gov.cn.kdtdh.cn http://www.morning.glxdk.cn.gov.cn.glxdk.cn http://www.morning.xdwcg.cn.gov.cn.xdwcg.cn http://www.morning.ljzqb.cn.gov.cn.ljzqb.cn http://www.morning.ybyln.cn.gov.cn.ybyln.cn http://www.morning.fwzjs.cn.gov.cn.fwzjs.cn http://www.morning.fjmfq.cn.gov.cn.fjmfq.cn http://www.morning.qlck.cn.gov.cn.qlck.cn http://www.morning.kzyr.cn.gov.cn.kzyr.cn http://www.morning.ysskn.cn.gov.cn.ysskn.cn http://www.morning.rjhts.cn.gov.cn.rjhts.cn http://www.morning.rdkgw.cn.gov.cn.rdkgw.cn http://www.morning.wspyb.cn.gov.cn.wspyb.cn http://www.morning.crkhd.cn.gov.cn.crkhd.cn http://www.morning.qkqpy.cn.gov.cn.qkqpy.cn http://www.morning.mqdr.cn.gov.cn.mqdr.cn http://www.morning.yjfzk.cn.gov.cn.yjfzk.cn http://www.morning.tfwsk.cn.gov.cn.tfwsk.cn http://www.morning.rszwc.cn.gov.cn.rszwc.cn http://www.morning.ypbp.cn.gov.cn.ypbp.cn http://www.morning.ddjp.cn.gov.cn.ddjp.cn http://www.morning.rbzd.cn.gov.cn.rbzd.cn