1、类模板
一个类模板(也称为类属类或类生成类)允许用户为类定义一种模式,使得类中的某些数据成员、默写成员函数的参数、某些成员函数的返回值,能够取任意类型(包括系统预定义的和用户自定义的)。如果一个类中数据成员的数据类型不能确定,或者是某个成员函数的参数或返回值的类型不能确定,就必须将此类声明为模板,它的存在不是代表一个具体的、实际的类,而是代表着一类类。
类模板的重点是模板。表示的是一个模板,专门用于产生类的模子。例如:
template <typename T>
class Vector
{
…
};
使用这个Vector模板就可以产生很多的class(类),Vector<int>、Vector<char>、Vector< Vector<int> >、Vector<Shape*>……。
2、 模板类
模板类的重点是类。表示的是由一个模板生成而来的类。例如: 上面的Vector<int>、Vector<char>、……全是模板类。
3、类模板的定义
3.1首先要定义类,其格式为:
template <class T>
class foo
{
……
}
foo 为类名,在类定义体中,如采用通用数据类型的成员,函数参数的前面需加上T,其中通用类型T可以作为普通成员变量的类型,还可以作为const和static成员变量以及成员函数的参数和返回类型之用。例如:
template<class T>
class Test{
private:
T n;
const T i;
static T cnt;
public:
Test():i(0){}
Test(T k);
~Test(){}
void print();
T operator+(T x);
};
3.2在类定义体外定义成员函数时,若此成员函数中有模板参数存在,则除了需要和一般类的体外定义成员函数一样的定义外,还需在函数体外进行模板声明,例如
template<class T>
void Test<T>::print(){
std::cout<<"n="<<n<<std::endl;
std::cout<<"i="<<i<<std::endl;
std::cout<<"cnt="<<cnt<<std::endl;
}
如果函数是以通用类型为返回类型,则要在函数名前的类名后缀上“<T>”。例如:
template<class T>
Test<T>::Test(T k):i(k){n=k;cnt++;}
template<class T>
T Test<T>::operator+(T x)
{
return n + x;
}
3.3 在类定义体外初始化const成员和static成员变量的做法和普通类体外初始化const成员和static成员变量的做法基本上是一样的,唯一的区别是需在对模板进行声明,例如
template<class T>
int Test<T>::cnt=0;
template<class T>
Test<T>::Test(T k):i(k){n=k;cnt++;}
4、类模板的使用
4.1普通类继承模板类
template<class T>
class TBase
{
T data;
……
};
class subClass:public TBase<int>
{
……
};
可能会出现以下情况:
template<class T>
class TBase
{
T data;
……
};
class subClass:public TBase<subClass>
{
……
};
这种情况一般TBase类中放的是subClass的构造函数和析构函数,而subClass可以对构造函数和析构函数进行重载
4.2模板类继承普通类(较常见)
class Base{
……
};
template<class T>
class TsubClass:public Base{
T data;
……
};
4.3类模板继承类模板
template<class T>
class TBase{
T data1;
……
};
template<class T1,class T2>
class TsubClass:public TBase<T1>{
T2 data2;
……
};
4.4模板类继承模板参数给出的基类(继承哪个基类由模板参数决定)
#include<iostream>
using namespace std;
class BaseA
{
public:
BaseA(){cout<<"BaseA founed"<<endl;}
};
class BaseB
{
public:
BaseB(){cout<<"BaseB founed"<<endl;}
};
template<typename T, int rows>
class BaseC
{
private:
T data;
public:
BaseC():data(rows)
{
cout<<"BaseC founed "<< data << endl;
}
};
template<class T>
class TsubClass:public T
{
public:
TsubClass():T(){cout<<"TsubClass founed"<<endl;}
};void main(){
TsubClass<BaseA> x;// BaseA作为基类
TsubClass<BaseB> y;// BaseB作为基类
TsubClass<BaseC<int, 3> > ; // BaseC<int,3>作为基类
}
5、C++中易混淆的几个概念
5.1函数指针与指针函数
函数指针的重点是指针,表示的是一个指向函数的指针。例如:
int (*pf)();
指针函数的重点是函数。表示的是一个函数,它的返回值是指针。例如:
int* fun();
5.2
数组指针与指针数组
数组指针的重点是指针。表示的是一个指针,它指向的是一个数组,例如:
int (*pa)[8];
指针数组的重点是数组。表示的是一个数组,它包含的元素是指针。例如;
int* ap[8];
5.3 函数模板与模板函数
函数模板的重点是模板。表示的是一个模板,专门用来生产函数。例如:
template <typename T>
void fun(T a)
{
...
}
在运用的时候,可以显式(explicitly)生产模板函数,fun<int>、fun<double>、fun<Shape*>……。也可以在使用的过程中由编译器进行模板参数推导,帮你隐式(implicitly)生成。
fun(6);//隐式生成fun<int>
fun(8.9);//隐式生成fun<double>
fun(‘a’);// 隐式生成fun<char>
Shape* ps = new Cirlcle;
fun(ps);//隐式生成fun<Shape*>
模板函数的重点是函数。表示的是由一个模板生成而来的函数。例如:上面显式(explicitly)或者隐式(implicitly)生成的fun<int>、fun<Shape*>……都是模板函数。