C++之模板

一函数模板

重载函数通常基于不同的数据类型实现相似的操作,如果对不同数据类型的操作完全相同,那么使用函数模板更加简洁方便。函数模板是对相同逻辑结构(不同数据类型)数据对象操作的抽象,是生成不同类型参数的重载函数的“模板”.
模板说明:说明模板中使用的类属参数。
说明形式:
template<class T1,class T2,...,class Tn>’
冠以class的类型形式参数T,ElementType,typename等是等待实例化的类属参数。所对应可以是int,double,char,指针,类等类型。
实例:

//Max.h
#ifndef MAX_H
#define MAX_H
template<typename T>
T Max(const T a,const T b)
{
return a>b?a:b;
}
#endif
//ex10_1.cpp
#include <iostream>
#include "Max.h"
using namespace std;
int main()
{
int j,k;
cout<<"Enter two integer:\n";
cin>>j>>k;
cout<<"Max("<<j<<","<<k<<")="<<Max(j,k)<<endl;
double x,y;
cout<<"Enter two double:\n";
cin>>x>>y;
cout<<"Max("<<x<<","<<y<<")="<<Max(x,y)<<endl;
char c,h;
cout<<"Enter two character:\n";
cin>>c>>h;
cout<<"Max("<<c<<","<<h<<")="<<Max(c,h)<<endl;
}

对函数模板调用过程:1实例化,函数模板-》模板函数
2与普通函数调用一致

二重载函数模板

便于定义类属参数,或者由于函数参数的类型,个数不相同所进行的类似操作。

//重载上一个例子的函数,找出数组中的最大元素
template<typename T>
T Max(const T *a,int n)
{
T temp;
int i;
temp=a[0];
for(i=1;i<n;i++)
if(a[i]>temp)temp=a[i];
return temp;
}

编译器函数调用匹配顺序:
1寻找和使用最符合函数名和参数类型的函数,若找到,则调用它。
2否则,寻找一个函数模板,将其实例化,产生一个匹配的函数模板,若找到,则调用它。
3否则,寻找可以通过参数类型转换进行参数匹配的重载函数,若找到,则调用它。
4否则,则调用错误或者如果调用选择多于1个,则调用匹配出现二义性,也是错误的。

三类模板

由模板说明和类说明组成。

//一个数组类模板
//Array.h
#ifndef ARRAY_H
#define ARRAY_H
template<typename T>
class Array
{
public:
Array(int s);
virtual ~Array();
virtual const T& Entry(int index)const;
virtual void Enter(int index,const T &value);
protected:
int size;
T * element;
};
template<typename T>Array<T>::Array(int s)
{
if(s>1)size=s;
else size=1;
element=new T[size];
}
template<typename T>Array<T>::~Array()
{
delete[] element;
}
template<typename T>const T& Array<T>::Entry(int index)const
{
return element[index];
}
template<typename T>void Array<T>::Enter(int index,const T& value)
{
element[index]=value;
}
#endif
//类模板的成员函数都是函数模板,实现语法和函数模板类似,如果在类中定义,则不需要特别说明,如果在类外,则每个成员函数定义都要冠以模板参数说明,并且在指定类名时要后跟类属参数。
Array<int>IntAry(5);//实例化
//执行过程:编译器用类型int对类模板进行实例化,生成模板类;调用构造函数,实例化模板类,建立对象IntAry;

四在类层次中的类模板

一个类模板在类层次结构中,既可以是基类,也可以是派生类,即:类模板可以从类模板派生或从普通类派生;模板类可以从类模板中派生或普通类派生。

//从类模板Array<T>派生类模板
//BoundArray.h
#ifndef BOUNDARRAY_H
#define BOUNDARRAY_H
template<class T>
class BoundArray:public Array<T>
{
public:
BoundArray(int low=0,int height=1);
virtual const T& Entry(int index)const;
virtual void Enter(int index,const T& value);
private:
int min;
};
template<class T>
BoundArray<T>::BoundArray(int low,int height):Array<T>(height-low+1)
{
if(height-low<0)
{
cout<<"Beyond the bounds of Array.\n";
exit(1);
}
min=low;
}
template <class T>
const T& BoundArray<T>::Entry(int index)const
{
if(index<min||index>min+size-1)
{
cout<<"Beyond the bounds of index.\n";
exit(1);
}
return Array<T>::Entry(index-min);
}
template<class T>
void BoundArray<T>::Enter(int index,const T& value)
{
if(index<min||index>min+size-1)
{
cout<<"Beyond the bounds of index.\n";
exit(1);
}
Array<T>::Enter(index-min,value);
}
#endif
//调用
BoundArray<int> b(low,height);
执行过程:
编译器从类模板BoundArray<T>首先生成基类Array<T>的模板类Array<int>;再生成一个模板类BoundArray<int>继承Array<int>的数据和操作.
//从类模板派生模板类
#include <iostream>
using namespace std;
template<typename T>
class A
{
public:
A(T x){t=x;}
void out(){cout<<t<<endl;}
protected:
T t;
};
class B:public A<int>
{
public:
B(int a,double x):A<int>(a)
{y=x;}
void out()
{A<int>::out();cout<<y<<endl;}
protected:
double y;
};
int main(){
A<int>a(123);
a.out();
B b(789,5.16);
b.out();
}

五类模板与友元
1模板类的友元函数
友元函数是一般函数

template<typename T>class X
{
//***
friend void f1();
}

友元函数是函数模板

template<typename T>class X
{
template<typename T>friend void f2(X<T>&);
} 

模板类的友元类

//声明Y类的每个成员函数成为类模板X实例化的每个模板类的友元函数
template<typename T>class X
{
friend class Y;
}
//类模板的友元类是类模板
template<typename T>class X{
template <typename T>friend class Z;
}
//复数类模板
#include <iostream>
using namespace std;
template<typename T>
class Complex
{
public:
Complex(T r=0,T i=0);
private :
T Real,Image;
template<typename T>
friend Complex<T>operater+(const Complex<T> c1,const Complex<T> c2);
template<typename T>
friend Complex<T>operater-(const Complex<T>&c1,const Complex<T>&c2);
template<typename T>
friend Complex<T>operater-(const Complex<T>&c);
template<typename T>
friend ostream & operater<<(ostream &output,const Complex<T>&c);
};
template<typename T>
Complex<T>::Complex(T r,T i){
Real=r;
Image=i;
}
template<typename T>Complex<T> operator+(const Complex<T> c1,const Complex<T> c2){
T r=c1.Real+c2.Real;
T i=c1.Image+c2.Image;
return Complex<T>(r,i);
}
template<typename T>Complex<T> operator-(const Complex<T>&c1,const Complex<T>&c2)
{
T r=c1.Real-c2.Real;
T i=c1.Image-c2.Image;
return Complex<T>(r,i);
}
template<typename T>
Complex<T>operater-(const Complex<T>&c)
{
return Complex<T>(-c.Real,-c.Image);
}
template<typename T>
ostream & operater<<(ostream &output,const Complex<T>&c)
{
output<<'('<<c.Real<<","<<c.Image<<')';
return output;
}
int main()
{
Complex<double> c1(2.5,3.7),c2(4.2,6.5);
cout<<"c1="<<c1<<"\nc2="<<c2<<endl;
cout<<"c1+c2"<<c1+c2<<endl;
cout<<"c1-c2"<<c1-c2<<endl;
cout<<"-c1"<<-c1<<endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值