泛型编程与面向对象编程的目标相同即使重用代码和抽象通用概念的技术更加简单。但是面向对象编程强调编程的数据方面泛型编程强调的是独立于特定数据类型。这一篇介绍一下 C 编程中与面向对象并列的另一大分支——泛型编程这一篇主要介绍函数模板、类模板和成员模板三大部分如有侵权请联系删除如有错误欢迎大家指正谢谢泛型编程模板是泛型编程的一种重要思想STL(Standard Template Library标准模板库)是采用模板实现的一个实例函数模板对比函数重载(同一作用域内函数名相同参数列表不同的函数)函数模板只需要一个函数就实现了函数重载的部分功能(参数个数相同类型不同函数重载需要定义多个同名参数列表不同的函数)123456789templatetypenameT,typenameY// 这也可以写 templateclass T, class Y 此处的 class 和 typename 作用相同voidtfunc(T t, Y y) {cout t y endl;}intn 2;doubled 2.1;tfunc(n, d);// 运行结果2 2.1函数模板具体化函数模板具体化就是将某一(某几)个要处理的类型单独处理需要单独写一个实现形式是 template void fun(type t);函数模板的具体化和普通函数可以同时存在调用顺序是 普通函数 函数模板具体化 模板函数12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152// 测试一函数模板针对特殊数据类型具体化 structNode {intval;Node* next;};// 函数模板templatetypenameTvoidtfunc(constT t) {cout template: t endl;}// 函数模板具体化(用于处理Node类型数据)templatevoidtfuncNode(constNode node) {cout templateNode: node.val endl;}// 函数模板具体化(用于处理int类型数据)templatevoidtfuncint(constint n) {cout templateint: n endl;}// 普通函数voidtfunc(constint n) {cout tfunc(): n endl;}doubled 2.1;tfunc(d);// 函数模板未具体化double类型函数调用模板Node node{ 2, nullptr };tfunc(node);// 函数模板具体化Node类型函数调用函数模板的具体化intn 2;tfunc(n);// 函数模板具体化int类型函数也存在普通函数调用普通函数// 测试二函数模板部分具体化 templatetypenameT1,typenameT2voidtfunc(T1 t1, T2 t2) {cout typeid(T1).name() and typeid(T2).name() : t1 t2 endl;}templatetypenameT1voidtfunc(T1 t1,inti) {cout typeid(T1).name() and int: t1 i endl;}templatetypenameT2voidtfunc(longl, T2 t2) {cout long and typeid(T2).name() : l t2 endl;}templatevoidtfunc(shortl,inti) {cout long and int: l i endl;}// 分别调用以上四个模板函数tfunc(char(c),char(c));tfunc(char(c),int(10));tfunc(long(10),char(c));tfunc(short(10),int(10));函数模板实例化让编译器生成指定类型的函数定义不用写函数的实现形式是 template void fun(type t);12345678// 函数模板templatetypenameTvoidtfunc(constT t) {cout template: t endl;}// 函数模板实例化不用写函数的实现编译器会生成该类型的模板具体化函数templatevoidtfuncchar(constchar c);类模板类模板可以指定默认模板参数(函数模板不可以)跟函数参数的默认值一样必须从右向左连续赋值默认类型如果实例化对象时又传递了类型默认类型会被覆盖掉跟函数参数是一样的创建对象时需要传递模板参数列表模板参数列表加在类名后面 ClassName typename T classN; 如果类的模板参数列表有默认值可以不传模板参数但一定要加 如 ClassName classN; 创建堆区对象的时候所有的类名称后面都要加模板参数列表如 ClassName typename T * classN new ClassName typename T; 除了类内其他地方出现 ClassName 的地方一般都要加模板参数列表12345678910111213141516171819templatetypenameT int,typenameY char// 此处指定了模板默认参数部分指定必须从右到左指定classTest {public:Test(T t, Y y) : t(t), y(y) {}voidtfunc();private:T t;Y y;};templatetypenameT,typenameY// 类模板的函数在类外实现需要加上模板参数列表但不需要加指定的默认模板参数voidTestT, Y::tfunc() {// 类外使用Test需要加模板参数cout t y endl;}intn 2;doubled 2.1;Testint,double test(n, d);// 此处如果使用默认模板参数可定义为 Test test(int(2), char(a));test.tfunc();// 运行结果2 2.1类模板的继承类模板被继承后参数的传递方式主要有两种一种是直接在子类继承父类的时候为父类指定固定的类型二是通过子类模板参数列表传递
C++ 泛型编程详解
泛型编程与面向对象编程的目标相同即使重用代码和抽象通用概念的技术更加简单。但是面向对象编程强调编程的数据方面泛型编程强调的是独立于特定数据类型。这一篇介绍一下 C 编程中与面向对象并列的另一大分支——泛型编程这一篇主要介绍函数模板、类模板和成员模板三大部分如有侵权请联系删除如有错误欢迎大家指正谢谢泛型编程模板是泛型编程的一种重要思想STL(Standard Template Library标准模板库)是采用模板实现的一个实例函数模板对比函数重载(同一作用域内函数名相同参数列表不同的函数)函数模板只需要一个函数就实现了函数重载的部分功能(参数个数相同类型不同函数重载需要定义多个同名参数列表不同的函数)123456789templatetypenameT,typenameY// 这也可以写 templateclass T, class Y 此处的 class 和 typename 作用相同voidtfunc(T t, Y y) {cout t y endl;}intn 2;doubled 2.1;tfunc(n, d);// 运行结果2 2.1函数模板具体化函数模板具体化就是将某一(某几)个要处理的类型单独处理需要单独写一个实现形式是 template void fun(type t);函数模板的具体化和普通函数可以同时存在调用顺序是 普通函数 函数模板具体化 模板函数12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152// 测试一函数模板针对特殊数据类型具体化 structNode {intval;Node* next;};// 函数模板templatetypenameTvoidtfunc(constT t) {cout template: t endl;}// 函数模板具体化(用于处理Node类型数据)templatevoidtfuncNode(constNode node) {cout templateNode: node.val endl;}// 函数模板具体化(用于处理int类型数据)templatevoidtfuncint(constint n) {cout templateint: n endl;}// 普通函数voidtfunc(constint n) {cout tfunc(): n endl;}doubled 2.1;tfunc(d);// 函数模板未具体化double类型函数调用模板Node node{ 2, nullptr };tfunc(node);// 函数模板具体化Node类型函数调用函数模板的具体化intn 2;tfunc(n);// 函数模板具体化int类型函数也存在普通函数调用普通函数// 测试二函数模板部分具体化 templatetypenameT1,typenameT2voidtfunc(T1 t1, T2 t2) {cout typeid(T1).name() and typeid(T2).name() : t1 t2 endl;}templatetypenameT1voidtfunc(T1 t1,inti) {cout typeid(T1).name() and int: t1 i endl;}templatetypenameT2voidtfunc(longl, T2 t2) {cout long and typeid(T2).name() : l t2 endl;}templatevoidtfunc(shortl,inti) {cout long and int: l i endl;}// 分别调用以上四个模板函数tfunc(char(c),char(c));tfunc(char(c),int(10));tfunc(long(10),char(c));tfunc(short(10),int(10));函数模板实例化让编译器生成指定类型的函数定义不用写函数的实现形式是 template void fun(type t);12345678// 函数模板templatetypenameTvoidtfunc(constT t) {cout template: t endl;}// 函数模板实例化不用写函数的实现编译器会生成该类型的模板具体化函数templatevoidtfuncchar(constchar c);类模板类模板可以指定默认模板参数(函数模板不可以)跟函数参数的默认值一样必须从右向左连续赋值默认类型如果实例化对象时又传递了类型默认类型会被覆盖掉跟函数参数是一样的创建对象时需要传递模板参数列表模板参数列表加在类名后面 ClassName typename T classN; 如果类的模板参数列表有默认值可以不传模板参数但一定要加 如 ClassName classN; 创建堆区对象的时候所有的类名称后面都要加模板参数列表如 ClassName typename T * classN new ClassName typename T; 除了类内其他地方出现 ClassName 的地方一般都要加模板参数列表12345678910111213141516171819templatetypenameT int,typenameY char// 此处指定了模板默认参数部分指定必须从右到左指定classTest {public:Test(T t, Y y) : t(t), y(y) {}voidtfunc();private:T t;Y y;};templatetypenameT,typenameY// 类模板的函数在类外实现需要加上模板参数列表但不需要加指定的默认模板参数voidTestT, Y::tfunc() {// 类外使用Test需要加模板参数cout t y endl;}intn 2;doubled 2.1;Testint,double test(n, d);// 此处如果使用默认模板参数可定义为 Test test(int(2), char(a));test.tfunc();// 运行结果2 2.1类模板的继承类模板被继承后参数的传递方式主要有两种一种是直接在子类继承父类的时候为父类指定固定的类型二是通过子类模板参数列表传递