第11章 模板

更新时间:2024-06-07 18:29:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

第11章模板

【内容提要】 模板的概念

函数模板的定义和使用 类模板的定义和使用 【重点与难点】 11.1 模板的概念

模板是实现代码复用的一种工具,它可以实现类型参数化,把类型定义为参数,实现代码的真正复用。

模板分两类:函数模板和类模板。用一个代码段指定一组函数称为函数模板,或用一个代码段指定一组相关类称为类模版。 11.2 函数模板的定义和使用 11.2.1 函数模板的定义

格式为:

template

<返回类型><函数名>(参数表) { 函数体

}

说明:

①template是定义模板函数的关键字;template后面的尖括号不能省略;

②typename是声明数据类型参数标识符的关键字,也可用class。它用以说明其后面的标识符是数据类型标识符。在这个函数定义中,凡希望根据实参数据类型来确定数据类型的变量,都可以用数据类型参数标识符来说明,从而使这个变量可以适应不同的数据类型。

③定义函数模板时,可以声明多个类型参数标识符,各标识符之间用逗号分开。

④函数模板只是声明了一个函数的描述即模板,不是一个可以直接执行的函数,只有根据实际情况用实参的数据类型代替类型参数标识符之后,才能产生真正的函数。 11.2.2 模板函数

在使用函数模板时,要将形参“数据类型参数标识符”实例化为确定的数据类型。将类型形参实例化的参数称为模板实参,用模板实参实例化的函数称为模板函数。 11.2.3 重载模板函数

函数模板可使用多种方式重载。可以使用其它函数模板,指定不同参数的相同函数名。 也可以用非模板函数重载。

用非模板函数重载函数模板有两种方法:

① 借用函数模板的函数体,只声明非模板函数的原型,它的函数体借用函数模板的函

数体。

② 重新定义函数体。即重新定义一个完整的非模板函数,它所带的参数可以随意。 在C++中,函数模板与同名的非模板函数重载时,应遵循下列调用原则: 首先寻找一个参数完全匹配的函数,若找到就调用它。若找不到,则寻找一个函数模板,将其实例化生成一个匹配的模板函数,若找到就调用它。若找不到,则从第一步中通过类型转换产生参数匹配,若找到就调用它。否则调用失败。

11.3 类模板的定义和使用 11.3.1 类模板的定义

格式为:

template class 类名 {

//……

};

说明:

① template是声明类模板的关键字,template后面的尖括号不能省略。

② 定义类模板时,可以声明多个类型参数标识符,各标识符之间用逗号分开。

③ 类模板定义中,凡要采用标准数据类型的数据成员、成员函数的参数或返回类型的

前面都要加上类型标识符。

④ 如果类中的成员函数要在类的声明之外定义,则它必须是模板函数。其定义形式为:

template

函数返回类型类名<数据类型参数标识符>∷函数名(数据类型参数标识符形参1,??,数据类型参数标识符形参n) {

函数体 }

⑤ 类模板使类中的一些数据成员和成员函数的参数或返回值可以取任意的数据类型。

类模板不是一个具体的类,它代表着一族类,是这一族类的统一模式。使用类模板就是要将它实例化为具体的类。

11.3.2 模板类

将类模板的模板参数实例化后生成的具体的类,就是模板类。由类模板生成模板类的一般形式为:

类名<模板实参表>对象名1,对象名2,?,对象名n; 【典型例题】

例题1.有如下函数模板定义: template

T func(T x, T y) { return x*x*x+y*y*y; } 在下列对func的调用中,错误的是()。 (a) func(3, 5); (b) func(3.0, 5.5); (c) func (3, 5.5); (d) func(3, 5.5); 解答:

本题主要考查函数模板的使用方法。这里选项a是将函数模板中的类型形参实例化为int型,选项b是将函数模板中的类型形参实例化为double型。选项c中函数func的两个实参一个为int型,一个为double型,无法使用该函数模板。选项d中模板实参被显式指定,显示指定模板实参的方法是用尖括号<>将用逗号隔开的实参类型列表括起来紧跟在函数模板实例的名字后面。如选项d将实参类型指定为int型。本题答案为:c。

例题2.有如下程序: template class Array {

protected: int num T *p; public: Array(int); ~Array(); };

Array::Array(int x)// ① { num=x;// ② p=new T[num];}// ③ Array::~Array()//④ { delete []p;// ⑤ }

void main()

{ Array a(10);// ⑥ }

其中有错误的语句为__________________,应改正为_______________________________。 解答:

本题主要考查类模板的定义和使用。如果类中的成员函数要在类的声明之外定义,则它必须是模板函数。其定义形式为:

template

函数返回类型类名<数据类型参数标识符>∷函数名(数据类型参数标识符形参1,??,数据类型参数标识符形参n) {

函数体 }

本程序中类的构造函数和析构函数均在类中声明,类外定义。所以①、④语句关于这些函数的定义均错误,应遵循上边所述形式。由类模板生成模板类的一般形式为: 类名<模板实参表>对象名1,对象名2,?,对象名n; ⑥语句对类模板的使用错误。所以本题答案为:①、④、⑥ 改正程序:

①template

Array::Array(int x) ④template Array::~Array() ⑥Array a(10);

例题3.运行下列程序结果为___________________________。 #include #include

template T add(T a, U b) { return(a + b); }

char* add(char *a,char *b ) { return strcat(a,b); }

void main() {

int x=1,y=2;

double x1=1.1,y1=2.2; char p[10]=\ cout<

cout<

解答:

本题主要考查对函数模板的定义与使用以及重载模板函数的理解。 在C++中,函数模板与同名的非模板函数重载时,应遵循下列调用原则:

首先寻找一个参数完全匹配的函数,若找到就调用它。若找不到,则寻找一个函数模板,将其实例化生成一个匹配的模板函数,若找到就调用它。若找不到,则从第一步中通过类型转换产生参数匹配,若找到就调用它。否则调用失败。本题中主函数对函数add的四次调用中前三次都是未找到参数完全匹配的函数,于是找到一个函数模板,将该函数模板实例化为模板函数。第四次调用时找到了参数完全匹配的函数,于是调用了该函数。所以本题答案为:

3,3.3,3.1,C++ program。

例题4.下列关于类模板的模板参数说法正确的是()。

(a)只可作为数据成员的类型 (b)只可作为成员函数的参数类型 (c)只可作为成员函数的返回值类型 (d)以上三者都可以 解答:

类模板中的模板参数既可以作为类成员的类型,也可作为成员函数的参数类型还可作为成员函数的返回值类型。本题答案为:d。

例题5.有如下类模板的定义,请指出其中的错误___________________________。 template

class A {public: T num;} 解答:

类模板的定义还是在定义类,所以类定义结束的分号不能少。答案为:定义语句的最后缺少一个分号。

例题6.下列说法正确的是()。

(a) 如果从一个带单个static数据成员的类模板产生几个模板类,则每个模板类共享类模板static数据成员的一个副本。

(b) 模板函数可以用同名的另一个模板函数重载。 (c) 同一个形参名只能用于一个模板函数。

(d) 关键字class指定函数模板类型参数,实际上表示“任何用户自定义类型”。 解答:

在非模板类中,类的所有对象共享一个static数据成员。从类模板实例化的每个模板类有自己的类模板static数据成员,该模板类的所有对象共享一个static数据成员。每个模板类有自己的类模板的static数据成员副本。每个模板类有自己的静态数据成员副本。所以选项a错误。同一形式参数名可以用于多个模板函数。选项c错误。关键字class指定函数模板的类型参数,实际上表示“任何内部类型或用户自定义类型”。选项d错误。答案为:b

例题7.下面是3个数字求和的类模板程序。请将程序补充完整。 #include

template class sum{ T array[size]; public: sum(T a,T b,T c){array[0]=a;array[1]=b;array[2]=c;} T s(){return ________________________;} };

void main() { _______________ s1(1,2,3); //定义类对象 cout<

解答:

本题主要考查对类模板的应用。答案为:int size,array[0]+array[1]+array[2], sum

例题8.定义一个求幂函数的函数模板。 解答: 参考程序:

#include template T Power(T a, int exp)

{ T ans = a; while(--exp>0) ans*=a; return ans; }

int main() { cout << \ cout << \ return 0; } 【习题】 一、选择题

1.模板对类型的参数化提供了很好的支持,因此()。 (a) 类模板的主要作用是生成抽象类 (b) 类模板实例化时,编辑器将根据给出的模板实参生成一个类(c) 在类模板中的数据成员都具有同样类型 (d) 模板中的成员函数都没有返回值

2.有如下模板:

template T fun(U u){return u;}

下列对模板函数fun的调用中错误的是()。

(a) a(97); (b) a(97); (c) a(97);

3.关于关键字class和typename,下列表述中正确的是()。 (a)程序中的typename都可以替换为class (b)程序中的class都可以替换为typename

(c)在模板形参表中只能用typename来声明参数的类型

(d)在模板形参表中只能用class或typename来声明参数的类型

4.运行下列程序的结果为()。 #include template void swap(T &a, T &b) { T temp; temp = a; a = b; b = temp; }

void swap(int &a, int &b) {

int temp; temp = a; a = b; b = temp;

cout<<\}

int main(void) {

int i=1, j=2;

double x=1.1, y=2.2; char a='x', b='z';

swap(i,j);

(d) a(97);

swap(a,b); swap(x,y);

cout<(a) (b) (c) (d)

2,1 swap two int swap tow int swap tow int z,x 2,1 swap tow int swap tow int 2.2,1.1 z,x 2,1 swap tow int 2.2,1.1 z,x 2,1 2.2,1.1 z,x 2.2,1.1

5.设有函数模板 template T max(T a,T b) { return (a>b)?a:b; }

则下列语句中对该函数模板的错误使用是()。

(a)max(1,2) (b)max(2.3,4.5) (c)max(1,2.3) (d)max(‘a’,’b’)

6.关于在调用模板函数时模板实参的使用,下列描述正确的是()。

(a)对于虚拟类型参数所对应的模板实参,如果能从模板函数的实参中获得相同的信息,则都可以省略。

(b)对于虚拟类型参数所对应的模板实参,如果它们是参数表中的最后的若干个参数,则都可以省略。

(c)对于虚拟类型参数所对应的模板实参,若能够省略则必须省略。 (d)对于常规参数所对应的模板实参,任何情况下都不能省略。

二、填空题

1.模板是实现类属机制的一种工具,其功能非常强大,它既允许用户构造类属函数,即______________;也允许用户构造类属类,即____________。

2.有如下函数模板定义,错误的语句是_______,应该正为______________________。 template ;//① T fun(T x)//② { return x;//③ }

3.运行下列程序的输出结果为____________________。 #include template class Tstack { enum {size=1000}; T stack[size]; int top; public: Tstack( ):top(0){ } bool push(const T &i){ if(top

{ stack[top++]=i; return true; } else return false; } bool pop(T &value){ if(top!=0) { value=stack[--top] ; return true; } else return false; } };

void main() { Tstack a; int x; a.push(1); a.push(2); a.pop(x); cout<

4.下面的程序输出结果是____________________。 #include template T sum(T *x,int size=0) { T a=0; for(int i=0;i

void main() { int array[]={1,2,3,4}; int arraysum=sum(array,4); cout<

5.下面是一个函数模板,用于实现从3个整数或浮点数中找出最大值。请将函数模板的定义补充完整。 template

T max(_______①_______,T c) { T x; x=(a>b)?(a):(b); _______②_________; }

6.有如下程序段,错误的语句是_______,应该正为______________________。 template //①

class A { T x,y;//② public: A(T i,T j):x(i),y(j){}//③ };

A(double) obj(1.1,2.2);// ④

7.下面是3个数字求和的类模板程序。请将该定义补充完整。 template class sum { T temp,m[size]; public: sum(T a,T b,T c){m[0]=a;m[1]=b;m[2]=c;} T s(){return ________②________;} //计算三个数的和 };

三、编程题

编写一个处理冒泡排序的函数模板,并设计主程序完成输入、排序和输出int型和double型数组的功能。 【参考答案】 一、选择题 1. b 2. d 3. d 4. b 5. c 6. d

二、填空题

1. 函数模板、类模板

2. ①、template 即去掉分号 3. 21 4. 10

5. ①T a,T b 、 ②return (x>c)?(x):(c) 6. ④、A obj(1.1,2.2);

7. ①int size=3 、② m[0]+m[1]+m[2]

三、编程题 参考程序如下: #include

template void bubble_sort(X *items, int size); template void show_items(X *items, int size); void main(void) {

int iarray[7] = {7, 5, 4, 3, 9, 8, 6};

double darray[5] = {4.2, 2.5, -0.9, 100.2, 3.0}; cout << \ show_items(iarray, 7);

cout << \ show_items(darray, 5); bubble_sort(iarray, 7); bubble_sort(darray, 5);

cout << \ show_items(iarray, 7);

cout << \

show_items(darray, 5); }

template void bubble_sort(X *items, int size) {

register int i, j; X temp;

for (i = 1; i < size; i++) for (j = size-1; j >= i; j--) if (items[j-1] > items[j]) {

temp = items[j-1]; items[j-1] = items[j]; items[j] = temp; } }

template void show_items(X *items, int size) {

int i;

for(i=0; i < size; i++)

cout << items[i] << \ cout << endl; }

本文来源:https://www.bwwdw.com/article/xbv6.html

Top