您的位置:首页 > 其它

模板的一些高级主题

2011-08-26 14:24 239 查看
十一、模板与继承1、当从模板类派生出子类时必须注意的是:子类并不会从通用的模板基类继承而来,只能从基类的某一实例继承而来。

这样的话就有以下几种继承方式:

a、基类是模板类的一个特定实例版本,比如template<class T> class B : public A<int>{};

b、基类是一个和子类相关的一个实例,比如template<class T> class B : public A<T>{};这时当实例化一个子类B的时候,基类就相应的被实例化为一个和子类相同的实例版本,比如B<int> m;模板类B被实例化为int 版本,这时基

类A也相应的被实例化为int版本。

c、template<class T> class B : public T 这种用法最普遍,也最难 ,ATL中广泛使用此法.属于基于模板的复用,和基于继承的复用不同.它非常巧妙的用了模板的特性模拟了C++的多态,而不是采用虚函数.

d、如果基类是一个特定的实例的版本,这时子类可以不是一个模板,比如class B : public A<int>{}。

//模板与继承的示例#include <iostream>#include <string>using std::string;using std::cout;using std::endl;//模板与继承的示例template<class T>class A{public: void ga() { cout<<"class A "<<typeid(T).name()<<endl; }};//以下是几种继承方式template<class T1> class B : public A<int>{public: void gb(){cout<<"class B "<<typeid(T1).name()<<endl;}};template<class T2> class C : public A<T2>{public: void gb(){cout<<"class C "<<typeid(T2).name()<<endl;}};//template<class T3> class D: public A<T>{} //错误,模板形参T在这里是不可见的说明符。错误原因在于,继承并不会从通用的基类中继承而来,只能是从某一特定的基类中继承而来。class E: public A<double>{}; //从特定实例继承时子类可以是一般的类void main(){ B<double> m; m.ga(); //输出class A int; m.gb(); //输出class B double; C<double> mc; mc.ga(); //输出class A double mc.gb(); //输出class C double}

十二、模板中的关键字typename和class的区别1、首先typename是一个较新的关键字,而class是比较老的关键字,在类模板的声明中使用哪个都是一样的。2、必须使用typename 关键字的情况:当有一个模板,且模板的类型形参和某一个类名同名,而且这个同名的类中又有一个嵌套类的时候就要使用关键字typename了,比如有类class T{public: class A{};}; 则template<class T> class B{T::Am;};这时的语句就会出错,因为模板类B 无法区别出T::A 表示的是一个类型还是一个数据成员,在C++里面默认情况下是一个数据成员,在这里的语句T::A m就会出错,会出现m前缺少类型说明符的错误。要使该式正确就必须在T::A前加上typename关键字以说明T::A表示的是一个类型。即template<class T> class B{typename T::A m;}这样就正确地声明了一个类T 的嵌套类A 的对象m。当然如果模板的类型形参和那个类名不同名时不会出现这种错误,比如把嵌套类B的外围类的类名改为D,则在模板类B中的语句D::B m;将是正确的语句。 #include "iostream"

using namespace std;//关键字typename 和class 的区别的示例class T{public: static int e; class B { public: void gb() { cout<<"class B"<<endl; } };}; //定义一个带有嵌套的类T。int T::e = 3;template<class T1> class A{public: T::B a;}; //模板形参与带有嵌套的类T不同名,所以这里的语句T::B a是正确的。当然在前面加上//typename关键字也不会出错。template<class T>class D{public: typename T::B b;}; //模板形参与带有嵌套类的类名同名,在语句T::B b;前必须加上typename以指//定这里的嵌套类B是一个类型而不是一个表达式。template<class T>class F{public: void g() { int a = T::e; cout<<a<<endl; }};//这个范例可以看出如果不在T::e前加typename则系统// 默认表示的是e是一个数据成员,而不是一个类型。int main(){ A<int> ma; ma.a.gb(); //输出class B D<int> md; md.b.gb(); //输出class B F<int> mf; mf.g();//输出数字3,在这里可以清楚的看到T::e默认表示的是一个数据成员而不是类型。}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: