0x00 前言
文章中的文字可能存在语法错误以及标点错误,请谅解;
如果在文章中发现代码错误或其它问题请告知,感谢!
本文档为个人边学习边记录的C++笔记,非教程,笔记中会存在引用他人文章内容的部分,被引用的原文不会被特殊标记出来,但会在参考文档中给出原文链接。
0x01 函数模板和类模板
C++最重要的特性之一就是代码重用,为了实现代码重用,代码必须具有通用性。
通用代码应不受数据类型的影响,并且可以自动适应数据类型的变化。这种程序设计类型称为参数化程序设计。
所谓多态性,就是将程序所处理的对象的类型参数化,使得一段程序可以用于处理多种不同类型的对象。
1 函数模板
函数模板的定义形式为:
template<模板参数表>
类型名 函数名(参数表)
{
函数体的定义
}
所有函数模板的定义都是用关键字template开始的,该关键字之后是使用尖括号<> 括起来的“模板参数表”,模板参数表由用逗号分隔的模板参数构成,可以包括以下内容: (1)class(或typename) 标识符,指明可以接收一个类型参数。这些类型参数代表的是类型,可以是内部类型或自定义类型。 (2)“类型说明符”标识符,指明可以接收一个由“类型说明符”所规定的常量作为参数。 (3)template<参数表> class标识符,指明可以接收一个类模板名作为参数。 类型参数可以用来指定函数模板本身的形参类型、返回值类型,以及声明函数中的局部变量。函数模板中函数体的定义方式预定义普通函数类似。 当类型参数的含义确定后,编译器将以函数模板为样板,生成一个函数,这一过程称为函数模板的实例化。
例:函数模板示例
#include<iostream>
using namespace std;
template<class T>
void outputArray(const T *array, int count){
for(int i = 0;i < count;i++){
cout<<array[i]<<" ";
}
cout<<endl;
}
int main(){
const int A_COUNT = 8, B_COUNT = 8, C_COUNT = 20;
int a[A_COUNT] = {1, 2, 3, 4, 5, 6, 7, 8};
double b[B_COUNT] = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8};
char c[C_COUNT] = "welcome to see you!";
cout<<"a array contains:"<<endl;
outputArray(a, A_COUNT);
cout<<"b array contains"<<endl;
outputArray(b, B_COUNT);
cout<<"c array contains:"<<endl;
outputArray(c, C_COUNT);
return 0;
}
运行结果:
a array contains:
1 2 3 4 5 6 7 8
b array contains
1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8
c array contains:
w e l c o m e t o s e e y o u !
当编译器检测到程序中调用函数模板outputArray时,便用outputArray的第一个实参类型替换掉整个模板定义中的T,并建立用来输出指定类型数组的一个完整的函数,然后再编译这个新建的函数。
虽然函数模板的适用刑事与函数类似,但二者有本质的区别,这主要表现在以下3个方面: (1)函数模板本身在编译时不会生成任何目标代码,只有由模板生成的实例会生成目标代码。 (2)被多个源文件引用的函数模板,应当联通函数体一同放在头文件中,而不能像普通函数那样只将声明放在头文件中。 (3)函数指针也只能指向模板的实例,而不能指向模板本身。
2 类模板
使用类模板使用户可以为类定义一种模式,使得类中的某些数据成员、某些成员函数的参数、返回值或局部变量能够取任意值(包括系统预定义的和用户自定义的) 类模板声明的语法形式是:
template<模板参数表>
class 类名
{
类成员声明
}
如果需要在类模板意外定义其成员函数,则要采用以下的形式:
template<模板参数表>
类型名 类名<模板参数表示符列表>::函数名(参数表)
使用一个模板类来建立对象时,应按如下形式声明:
模板名<模板参数表>对象名1,...,对象名n;
模板类的UML图表示如下,在途中,形式参数时T,把它用作类说明中的类型信息的占位符。
具有显式属性和操作的参数化类
通过把参数绑定到形式参数可以创建具体的类,这称为类模板的实例化。在UML语言中对类模板的实例化时通过使用绑定<<bind>> 构造型的依赖关系表示的。有两种说明绑定元素的形式,如下图所示: 表示为参数化A ,通过参数表来绑定
第一种形式
通过<< bind>>来绑定元素
第二种形式
例:类模板应用举例
类模板Store和类的关系图
#include <iostream>
#include<cstdlib>
using namespace std;
struct Student{
int id;
float gpa;
};
template<class T>
class Store{
private:
T item;
bool haveValue;
public:
Store();
T &getElem();
void putElem(const T &x);
};
template<class T>
Store<T>::Store():haveValue(false){}
template<class T>
T &Store<T>::getElem(){
if(!haveValue){
cout << "No item present!" << endl;
exit(1);
}
return item;
}
template<class T>
void Store<T>::putElem(const T &x){
haveValue = true;
item = x;
}
int main() {
Store<int>s1, s2;
s1.putElem(3);
s2.putElem(-7);
cout << s1.getElem() << " " << s2.getElem() << endl;
Student g = {1000, 23};
Store<Student>s3;
s3.putElem(g);
cout << "The student id is" << s3.getElem().id << endl;
Store<double>d;
cout << "Retrieving object d ...";
cout << d.getElem() << endl;
return 0;
}
运行结果:
3 -7
The student id is1000
Retrieving object d ...No item present!
以上。
参考文档: 郑莉 董渊 何江舟.《C++语言程序设计(第4版)》[M].北京:清华大学出版社。
|