关注,星标嵌入式客栈,精彩及时送达
[导读]最近用C编程,总结分享日常遇到的重要概念。 本文将共享模板类的原理和为什么需要模板类,以及使用时的基本点。
为什么需要模板,例如需要设计说明点的类。 大致上可以马上写如下。
classPoint_F{public:/*默认传入参数为0,0 */point _ f (float x0=0,floaty0=0) :x(x0 ),y ) y0 ) }floatget_y(const ) Returny; }private:/*通常将数据放在专用区域中,并将*/floatx隐藏在外部; 浮动; (; 问题是,在某些情况下,此点的坐标系可能不需要浮点。 例如,在接口设计中,中间点通常是整数表示,在这种情况下,需要设计另一个整数成员类。
classPoint_I{public:/*默认传入参数为0,0 */point _ f (int x0=0,inty0=0) :x(x0 ),y )/*初始化}private:/*通常将数据放在专用区域中,并将*/intx隐藏在外部; inty; (; 但是,在APP应用程式码中,您很清楚对不同资料成员的APP应用程式作业确实很相似。 此外,APP应用程式码可能会同时使用这两种成员资料类型。 只为了数据类型,必须愚蠢地重写原始代码。 在现代高级语言中,这显然是机械的。
是否可以将在c中具有不同成员数据类型但顶级逻辑相同的对象设计为一个类? 例如:
C模板编程正是为解决这种需求而设计的机制。 此机制允许函数或类使用泛型generic type进行操作。 因此,函数或类可以处理许多不同的数据类型,而不必为每个数据类型重写相应的类或函数。
是怎么实现的? 在这里,大致可以分为以下三种情况。
函数模板(Function templates)
类模板(Class templates)
*成员模板(成员模板) *
函数模板函数模板的基本语法范例如下:
templateclassidentifierfunction _ declaration; templatetypenameidentifierfunction _ declaration; template是模板关键字
typename identifier和class identifier定义函数参数泛型类型或函数主体类变量泛型类型
例如:
# includeiostreamusingnamespacestd; templatetypenamettmax(ta,Tb ) {returnab? a:b; }或写如下。
# includeiostreamusingnamespacestd; templateclassttmax(ta,Tb ) {返回ab? a:b; }中,将任务关键字class视为自定义类,而将typename视为int、float等基本数据类型的理解可能其实是错误的。 从c编译器的角度看,template typename T和template class T的含义相同,都很通用,当用户使用此模板函数时
关于上面的代码,你可能会问第一次使用的朋友是否可以随便导入班级。 这可能无法编译。 为什么呢? 传递的类必须支持操作员。 如果想对某个类使用该函数,但其本身不支持操作符,则必须实现操作符。
类模板与函数模板类似。 使用类内部成员数据或函数的参数或变量并在模板关键字中定义的泛型名称。 例如:
templatetypenametclasspoint _ t { public : point _ t (tx0=0,Ty0=0) :x(x0 ),y (y0 ) {}Tget_x ) consss }宣传
ivate: T x; T y;};这小段代码就回答了之前提出的问题,可以支持不同数据类型的点。
int main(){ Point_T<int> p1(1, 2); Point_T<float> p2(1.1f, 2.2f); cout << p1.get_x() << endl << p1.get_y() << endl; cout << p2.get_x() << endl << p2.get_y() << endl;}以上述简单例子看,分别构造了整型点p1,以及浮点型点p2,那么究竟怎么做到的呢?为了理解得更清楚,这里将其关键汇编代码段拷贝下来简要看看:
Point_T<int> p1(1, 2);000C1D6C push 2 000C1D6E push 1 000C1D70 lea ecx,[p1] 000C1D73 call Point_T<int>::Point_T<int> (0C11D1h) Point_T<float> p2(1.1f, 2.2f);000C1D78 push ecx 000C1D79 movss xmm0,dword ptr [__real@400ccccd (0C7B34h)] 000C1D81 movss dword ptr [esp],xmm0 000C1D86 push ecx 000C1D87 movss xmm0,dword ptr [__real@3f8ccccd (0C7B30h)] 000C1D8F movss dword ptr [esp],xmm0 000C1D94 lea ecx,[p2] 000C1D97 call Point_T<float>::Point_T<float> (0C1064h)可见编译器对不同类型参数实际上做了相应解析,相当于根据用户程序传入的参数编译出相应的多份代码。所以可以简单理解成编译器根据不同泛型实际参数类型生成了相应的处理代码。而前面所说的模板函数其原理也基本类似。
总结一下通过些简单例子,梳理一下模板函数以及模板类的基本概念以及原理,理解了这两个概念,就比较容易理解成员模板。所谓泛型模板编程,其本质是编译器针对不同参数类型解析解析生成相应的处理代码。学会使用模板泛型编程你会发现你会少写很多代码,代码看起来会比较优雅,而其实操作起来也没有想象中那么难。
—END—
往期精彩推荐,点击即可阅读
▲Linux驱动相关专辑
▲手把手教信号处理专辑
▲单片机相关专辑
分享 ???? 点赞 ???? 在看 ❤️
以“三连”行动支持优质内容!