设为首页 加入收藏

TOP

C++ chapter 10――模板(一)
2016-04-26 17:12:37 】 浏览:511
Tags:chapter 模板

**模板的概念
函数模板
类模板
名空间**

一、模板的概念
C++的模板提供对逻辑结构相同的数据对象通用行为的定义。模板运算对象的类型不是实际的数据类型,而是一种参数化的类型。
一个带类型参数的函数称为函数模板,一个带类型参数的类称为类模板。

二、函数模板

1、函数模板的概念
函数模板的基本原理是通过数据类型的参数化,将一组算法相同但所处理数据类型不同的重载函数凝练成一个函数模板。编译时,再由编译器按照函数模板自动生成针对不同数据类型的重载函数定义代码。
使用函数模板。对于函数模板,数据类型本身成了它的参数。

*2、函数模板的说明*
**格式:**template < typename T1, typename T2,… typename Tn>

template—模板说明关键字
typename—类型参数指定关键字(也可以是class)
T1,T2,…Tn—类型参数,是用户定义标识符,可实例化为任何内部类型或用户定义类型。

3、函数模板与模板函数
函数模板定义由模板说明和函数定义组成。
格式为:
template < typename T1,typename T2,…typename Tn>
<返回值类型> <函数名>(模板函数形参表)
{
//函数定义体
}
所有在模板说明的类型参数必须在函数定义中至少出现一次。函数参数表中可以使用类型参数,也可以使用一般参数。
注意:
(1)函数模板只是说明,不能直接执行,需要实例化为模板函数后才能执行。
(2)模板的类型参数由调用它的实际参数的具体数据类型替换,由编译器生成一段真正可执行的代码。这个过程称为实例化。
(3)一个函数模板用类型实例化后,称为模板函数

//eg10-1:用函数模板输出不同类型的数组
#include 
   
     using namespace std; template 
    
      //定义函数模板 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!"; 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; }
    
   

4、函数模板的优点
(1)函数模板方法克服了C语言用大量不同函数名表示相似功能的坏习惯;
(2)克服了宏定义不能进行参数类型检查的弊端;
(3)克服了C++函数重载用相同函数名字重写几个函数的繁琐。
因而,函数模板是C++中功能最强的特性之一,具有宏定义和重载的共同优点,是提高软件代码重用率的重要手段。

//eg10-2:用函数模板实现对n个元素的数组求最小值
#include 
   
     using namespace std; template 
    
      T min(T a[], int n) { int i; T minv = a[0]; for (i = 1; i
     
      a[i]) minv = a[i]; return minv; } int main() { int a[] = { 1, 3, 0, 2, 7, 6, 4, 5, 2 }; double b[] = { 1.2, -3.4, 6.8, 9, 8 }; cout << "a数组的最小值为:" << min(a, 9) << endl; cout << "b数组的最小值为:" << min(b, 4) << endl; return 0; }
     
    
   
//eg10-3:求两个不同类型数据的较大值
#include 
   
     using namespace std; template 
    
      T1 Max(T1 x, T2 y) { return x>(T1)y  x : (T1)y; } int main() { int i = 10, j = 56; float x1 = 50.34, x2 = 56.34; double y1 = 673.36, y2 = 465.972; cout << "the max of i,x1 is:" << Max(i, x1) << endl; cout << "the max of x1,y1 is:" << Max(x1, y1) << endl; cout << "the max of j,y2 is:" << Max(j, y2) << endl; return 0; } 
    
   

5、重载函数模板
函数模板与普通函数一样,也可以重载。可以定义同名的函数模板,提供不同的参数和实现;也可以用其他非模板函数重载。

(1)函数模板的重载

重载函数模板便于定义类型参数,或者函数模板参数的类型、个数不相同所进行的类似操作。
例如,例10-3的Max函数模板可以重载为求数组最大元素的函数模板。

//例10-4:函数模板重载
#include "iostream"
using namespace std;

template 
   
     T Max(T x, T y) { return (x>y)  x : y; }; template 
    
      T Max(T a[], int n) { T temp; int i; temp = a[0]; for (i = 1; i
     
      temp) temp = a[i]; return temp; } int main() { int i = 10, j = 56; float x1 = 50.34, x2 = 56.34; double y1 = 673.36, y2 = 465.972; double X[10] = { 1.2, 3.4, 8.9, 6.5, 9.3, 15.8, 3.8, 21.3, 11.2, 2.1 }; cout << "the max of i,j is:" << Max(i, j) << endl; cout << "the max of x1,x2 is:" << Max(x1, x2) << endl; cout << "the max of y1,y2 is:" << Max(y1, y2) << endl; cout << "The max element of X is:" << Max(X, 10) << endl; return 0; }
     
    
   

(2)用普通函数重载函数模板
函数模板实例化时,实际参数类型替换类型参数。虽然这种参数替换具有类型检查功能,却没有普通函数传值参数的类型转换机制。

例如:
对函数模板
template
T Max(T x,T y)
{
return (x>y)x:y;
};
调用时对应的两个实际参数必须类型相同。若有:
int k;char c;
则调用Max(k,c); 将出现语法错误。为了解决这一问题,可以用非模板函数重载一个同名的函数模板。

//例10-5:用普通函数重载函数模板
#include 
   
     using namespace std; template 
    
      T Max(T x, T y) { return (x>y)  x : y; }; int Max(char a, int b) //函数重载 { return(a>b  a : b); } int main() { int k = 98; char c = 'a'; double y1 = 673.36, y2 = 465.972; cout << "the max of k, c is : " << Max(k, c) << endl; //调用正确 cout << "the max of c, k is : " << Max(c, k) << endl; //调用正确 cout << "the max of y1,y2 is:" << Max(y1, y2) << endl; return 0; }
    
   

注意:
定义重载函数要注意避免二义性。
例如,在例10-5中,如果重载函数改为:
int Max(int a,int b)
{ return a>ba:b;}
将出现二义性,在调用时无法正确匹配。
Max(k,k);
//错误,不知调用T Max(T,T)还是Max(int,int)
Max(c,c); //错误

编译器调用函数的匹配规则:

(1)寻找和使用最符合函数名和参数类型的函数,若找到则调用它。
(2)否则,寻找一个函数模板,将其实例化产生一个匹配的模板函数,若找到则调用它。
(3)否则,寻找可以通过类型转换进行参数匹配的重载函数,若找到则调用它。

如果按以上步骤均未能找到匹配函数,则这个调用是错误的。
如果这个调用有多于一个的匹配选择,则调用匹配出现二义性,也是错误的。

在调用函数模板的程序员看来,函数模板与普通函数没有什么区别。唯一不同的是,函数模板 就像是一个具有通用类型的函数,可以处理不同类型的数据。

三、类模板

(1)应用模板技术,可以将一组功能相同但所处理数据类型不同的类凝练成一个类模板。编译时,再由编译器按照类模板自动生成针对不同数据类型的类定义代码。
(2)使用类模板可以为类声明一种模式,使得类中的某些数据成员、某些成员函数的参数、某些成员函数的返回值,能取任意类型(包括基本类型和用户自定义类型)。
(3)类模板与函数模板类似,它可以为各种不同的数据类型定义一种模板,在引用时使用不同的数据类型实例化该类模板,从而形成一个类的集合。

1、类模板与模板类
类模板由模板说明和类说明构成。格式为:
template
class 类名 { 类声明体 };
template < typename Type >
返回类型 类名<类型名表>::成员函数名1(形参表)
{ 成员函数1定义体 }

template
返回类型 类名<类型名表>::成员函数名n(形参表)
{ 成员函数n定义体 }

//例10-6:用类模板来处理任意类型的链表
#include 
   
     using namespace std; template 
    
      //声明模板 struct node //定义结构体类型模板 { T val; //val取任意类型,即模板参数类型 no
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇笔试题40. LeetCode OJ (27) 下一篇数据结构与算法――不相交集类的C..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目