C++面向对象入门(三十七)模板概念和初步认识类模板
强类型语言的特点:
1 程序可靠性较高:在编译运行前必须经过严格的类型检查, 达到在运行前就检查出类型不兼容的错误.
2 灵活性较低: 对于默写处理逻辑完全一样, 但是数据类型不同的变量的操作必须按照类型分别定义.
1 程序可靠性较高:在编译运行前必须经过严格的类型检查, 达到在运行前就检查出类型不兼容的错误.
2 灵活性较低: 对于默写处理逻辑完全一样, 但是数据类型不同的变量的操作必须按照类型分别定义.
解决强类型的严格性和灵活性的冲突的途径:
1 使用宏函数: 方便, 但是可能不带来其他安全问题, C++不提倡
2 为每个数据类型重载相同的函数, 麻烦
3 放松类型检查, 在编译时忽略, 推迟到运行期间作类型匹配检查, 可能在程序运行期间出现类型不兼容的情况
4 将数据类型作为参数(类属机制Genericity)
1 使用宏函数: 方便, 但是可能不带来其他安全问题, C++不提倡
2 为每个数据类型重载相同的函数, 麻烦
3 放松类型检查, 在编译时忽略, 推迟到运行期间作类型匹配检查, 可能在程序运行期间出现类型不兼容的情况
4 将数据类型作为参数(类属机制Genericity)
C++通过模板机制实现类属机制
模板机制: 一种参数化多态性的工具, 为逻辑功能相同而类型不同的程序提供代码共享机制
C++中的模板机制, 模板并非实实在在的函数或类, 仅仅是函数或类的描述, 模板运算对象的类型不是实际的数据类型,
而是一种参数化的类型(类属类型), 根据使用类似类型的构件, 又分为:
1 类模板:对一批仅有数据类型不同类的抽象, 只需为这一批类组成的整个类家族创建一个类模板, 然后给出一套程序代码, 就
可以用来生成多种具体类, 即模板类. 由于类模板需要一种或多种类型参数, 因此又被称为参数化类
优点:提高编程效率, 提高代码可重用性
而是一种参数化的类型(类属类型), 根据使用类似类型的构件, 又分为:
1 类模板:对一批仅有数据类型不同类的抽象, 只需为这一批类组成的整个类家族创建一个类模板, 然后给出一套程序代码, 就
可以用来生成多种具体类, 即模板类. 由于类模板需要一种或多种类型参数, 因此又被称为参数化类
优点:提高编程效率, 提高代码可重用性
类和类模板: 类是对一族具有公共性质的对象的抽象, 而类模板则是对一组具有公共性质的类的抽象, 类模板是更高层次的抽象化
如何定义类模板?
template<模板参数表>
class <类模板名>
{
<类成员声明>
}
template<模板参数表>
class <类模板名>
{
<类成员声明>
}
使用类模板的注意事项:
1 模板参数表包含一个多个用逗号分开的类型, 参数项可以包含基本数据类型, 也可以包含类类型, 如果是类类型, 必须加前缀class
或typename
2 类模板的成员函数和重载运算符必须为模板函数, 可以在类内定义, 定义方式和定义成员函数一致, 也可以放在类模板外部, 此时
定义方式如下
template<模板参数名>
<返回值类型> (如果返回值类型为引用类型,'&'在此处)<类模板名>< <类型名表> >::<成员函数名>(<参数表>)
{
<函数体>
}
3 与函数模板不同的是, 函数模板的实例化是由编译系统在处理函数调用时自动完成, 而类模板的实例化必须在程序中显式地指定
在类模板实例化为模板类时(使用类模板经实例化而成的具体类), 类模板中的成员函数自动实例化为模板函数
1 模板参数表包含一个多个用逗号分开的类型, 参数项可以包含基本数据类型, 也可以包含类类型, 如果是类类型, 必须加前缀class
或typename
2 类模板的成员函数和重载运算符必须为模板函数, 可以在类内定义, 定义方式和定义成员函数一致, 也可以放在类模板外部, 此时
定义方式如下
template<模板参数名>
<返回值类型> (如果返回值类型为引用类型,'&'在此处)<类模板名>< <类型名表> >::<成员函数名>(<参数表>)
{
<函数体>
}
3 与函数模板不同的是, 函数模板的实例化是由编译系统在处理函数调用时自动完成, 而类模板的实例化必须在程序中显式地指定
在类模板实例化为模板类时(使用类模板经实例化而成的具体类), 类模板中的成员函数自动实例化为模板函数
如何定义模板类对象
<类模板名>< <类型实参表> > <对象名>(<实参表>)
<类模板名>< <类型实参表> > <对象名>(<实参表>)
对于上述定义方式字段的解释:
类名名表: 类模板定义中的模板参数表中的参数名
类名名表: 类模板定义中的模板参数表中的参数名
如何实例化类模板?
语法:
<类模板名> < <类型实参表> >
语法:
<类模板名> < <类型实参表> >
2 函数模板: 可以一次定义出具有共性(除类型参数外, 其余全部相同)的一组函数, 同时也可以处理多种不同类型数据的函数
优点:增强了函数设计的通用性
优点:增强了函数设计的通用性
如何定义函数模板: 先实现函数模板, 然后实例化构造出相应的模板函数进行调用执行
定义函数模板的语法:
template<模板参数表>
<返回值类型> <函数名>(<参数表>)
{
<函数体>
}
template<模板参数表>
<返回值类型> <函数名>(<参数表>)
{
<函数体>
}
模板参数表的定义语法;
typename(class) 模板参数名,...
typename(class) 模板参数名,...
使用函数模板的注意事项:
1 模板参数可以在函数的任何地方使用
2 函数的参数表可以使用模板参数, 也可以使用一般类型参数(基本类型, 用户自定义类型), 但参数表至少又一个形参的
类型必须使用模板参数表的模板参数,
3 模板参数表中的每一个模板参数都必须在参数表中得到使用
4 函数模板的声明和定义必须是全局作用域, 模板不能被声明为类的成员函数
5 编译器不会为没有用到的任何类型生成相应的模板函数
6 一个类型无论使用多少次函数模板, 都只为该类型生成一个模板函数
1 模板参数可以在函数的任何地方使用
2 函数的参数表可以使用模板参数, 也可以使用一般类型参数(基本类型, 用户自定义类型), 但参数表至少又一个形参的
类型必须使用模板参数表的模板参数,
3 模板参数表中的每一个模板参数都必须在参数表中得到使用
4 函数模板的声明和定义必须是全局作用域, 模板不能被声明为类的成员函数
5 编译器不会为没有用到的任何类型生成相应的模板函数
6 一个类型无论使用多少次函数模板, 都只为该类型生成一个模板函数
代码示例:
#include <iostream> using namespace std; /* 强类型语言的特点: 1 程序可靠性较高:在编译运行前必须经过严格的类型检查, 达到在运行前就检查出类型不兼容的错误. 2 灵活性较低: 对于默写处理逻辑完全一样, 但是数据类型不同的变量的操作必须按照类型分别定义. 解决强类型的严格性和灵活性的冲突的途径: 1 使用宏函数: 方便, 但是可能不带来其他安全问题, C++不提倡 2 为每个数据类型重载相同的函数, 麻烦 3 放松类型检查, 在编译时忽略, 推迟到运行期间作类型匹配检查, 可能在程序运行期间出现类型不兼容的情况 4 将数据类型作为参数(类属机制Genericity) C++通过模板机制实现类属机制 模板机制: 一种参数化多态性的工具, 为逻辑功能相同而类型不同的程序提供代码共享机制 C++中的模板机制, 模板并非实实在在的函数或类, 仅仅是函数或类的描述, 模板运算对象的类型不是实际的数据类型, 而是一种参数化的类型(类属类型), 根据使用类似类型的构件, 又分为: 1 类模板:对一批仅有数据类型不同类的抽象, 只需为这一批类组成的整个类家族创建一个类模板, 然后给出一套程序代码, 就 可以用来生成多种具体类, 即模板类. 由于类模板需要一种或多种类型参数, 因此又被称为参数化类 优点:提高编程效率, 提高代码可重用性 类和类模板: 类是对一族具有公共性质的对象的抽象, 而类模板则是对一组具有公共性质的类的抽象, 类模板是更高层次的抽象化 如何定义类模板? template<模板参数表> class <类模板名> { <类成员声明> } 使用类模板的注意事项: 1 模板参数表包含一个多个用逗号分开的类型, 参数项可以包含基本数据类型, 也可以包含类类型, 如果是类类型, 必须加前缀class 或typename 2 类模板的成员函数和重载运算符必须为模板函数, 可以在类内定义, 定义方式和定义成员函数一致, 也可以放在类模板外部, 此时 定义方式如下 template<模板参数名> <返回值类型> (如果返回值类型为引用类型,'&'在此处)<类模板名>< <类型名表> >::<成员函数名>(<参数表>) { <函数体> } 3 与函数模板不同的是, 函数模板的实例化是由编译系统在处理函数调用时自动完成, 而类模板的实例化必须在程序中显式地指定 在类模板实例化为模板类时(使用类模板经实例化而成的具体类), 类模板中的成员函数自动实例化为模板函数 如何定义模板类对象 <类模板名>< <类型实参表> > <对象名>(<实参表>) 对于上述定义方式字段的解释: 类名名表: 类模板定义中的模板参数表中的参数名 如何实例化类模板? 语法: <类模板名> < <类型实参表> > 2 函数模板: 可以一次定义出具有共性(除类型参数外, 其余全部相同)的一组函数, 同时也可以处理多种不同类型数据的函数 优点:增强了函数设计的通用性 如何定义函数模板: 先实现函数模板, 然后实例化构造出相应的模板函数进行调用执行 定义函数模板的语法: template<模板参数表> <返回值类型> <函数名>(<参数表>) { <函数体> } 模板参数表的定义语法; typename(class) 模板参数名,... 使用函数模板的注意事项: 1 模板参数可以在函数的任何地方使用 2 函数的参数表可以使用模板参数, 也可以使用一般类型参数(基本类型, 用户自定义类型), 但参数表至少又一个形参的 类型必须使用模板参数表的模板参数, 3 模板参数表中的每一个模板参数都必须在参数表中得到使用 4 函数模板的声明和定义必须是全局作用域, 模板不能被声明为类的成员函数 5 编译器不会为没有用到的任何类型生成相应的模板函数 6 一个类型无论使用多少次函数模板, 都只为该类型生成一个模板函数 */ const int size = 10; //定义类模板 //实现数组的部分功能 template<typename AType> class aType { public: aType(AType arr[10]); AType &operator[](int n); private: AType array[10]; }; int main() { int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 }; aType<int> intArr(arr1); cout << intArr[3] << endl; double arr2[10] = { 1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9,11.0 }; aType<double> doubleArr(arr2); cout << doubleArr[6] << endl; cout << intArr[11] << endl; cout << doubleArr[-1] << endl; system("pause"); } /* template<模板参数名> <返回值类型> (如果返回值类型为引用类型,'&'在此处)<类模板名>< <类型名表> >::<成员函数名>(<参数表>) { <函数体> } */ template<typename AType> aType<AType>::aType(AType arr[]) { for (int i = 0; i < 10; i++) { array[i] = arr[i]; } } template<typename AType> AType &aType<AType>::operator[](int n) { if (n >= 10 || n < 0) { cout << "下标" << n << "超出范围!, 默认返回第一个元素" << endl; //exit(1); //运行后没反映, 不会出现终端框 return array[0]; } return array[n]; }
路漫漫其修远兮,吾将上下而求索。

浙公网安备 33010602011771号