29.为什么成员模板函数不能声明为虚函数。
因为,在编译器解析类的时候希望知道该类虚表的大小,如果允许成员模板虚函数,则必须提前知道所有该成员函数调用引起的实例化版本数量,这个需要扫描所有项目文件,非常不灵活,尤其在多项目文件的情况下。
30.为什么 模板的模板参数缺省值在所有地方必须出现?
。。。。。??
31.为什么通过单一模板参数声明的模板函数的多个函数参数,这些函数参数都由模板参数来定义,在调用时,即使给定的不同类型的参数有自动转换的路径,为什么还是要报错。
不符合模板函数声明,首先就找不到用来实例化的模板函数,根本走不到自动类型转换这一步。
32.类成员函数指针与普通函数指针的差别
a. 类成员函数指针是需要指向某类限定的名字空间中的函数,所以在声明时必须用类名来限定 void (className::*funcname)(paramlist)
b.因为类成员函数是需要通过类对象来调用以便设置this指针,所以在成员函数指针调用是也需要 objectName.*pfunc
c.成员函数指针,是指向某类名字空间下的具有指定参数列表和返回值的,所以在赋值时需要选取相应的类成员函数 pFunc=&className::funcname
33.什么是模板的半有序
取特殊程度最高的模板(和异常类型的匹配差不多),但是有时没有特化程度最高的,有多个并列的从而出现歧义,编译报错。
34.模板显示特化时,必须使用特化类型替换原来的模板参数类型,如果遇到const需要进行修正。
35.template<>说明所有参数都已经特化 , template<class T>说明T参数还没有特化。
36.为什么模板类只有被调用的成员函数才会实例化?
省事,省资源哇
37.函数模板不能特化只能重载。
38.由于模板类特化时要重新实现成员函数,所以特化的越多,代码工作量就越大。但是可以通过如下技巧减小代码量。
将需要特化的类型分为几个类别,然后为每个类别做一个完全特化,该类别下面的其他类型就从这个特化进行派生
例如:
template <class T>class Stack;
//完全特化
template<> class Stack<void *>
//为其他指针进行部分特化
template<class T> class Stack<T *> : private Stack<void *>
39.但编译器遇到一个标识符时,必须确定哪些信息,为什么?
必须确定类型、作用域
知道类型才能确定长度和其他关联信息,知道作用域才能确定该标识符出现的位置是否正确。
40.特征类。
比如需要一个画人物肖像的类,这个类需要根据操作的对象,画出不同的器官特征,那么可以使用特征类技术。
假设画肖像的类的操作为画出眼睛,鼻子,嘴巴。
那么先定义 几个类 ,大眼睛,小眼睛,挺鼻子,塌鼻子,小嘴巴,大嘴巴
然后定义几个对象的特征类,在特征类中设置特征名称,美女特征类(眼睛特征类为大眼睛,鼻子特征类为挺鼻子,嘴巴特征类为小嘴巴),丑女特征类(眼睛特征类为小眼睛,鼻子特征类为塌鼻子,嘴巴特征类为小嘴巴)
最后操作类中首先根据模板类型所代表的特征类来设置特征类型,后续直接操作特征类型。
又如:
#include <iostream>
using namespace std;
//牛奶类
class Milk
{
public:
friend ostream & operator << (ostream & os,const Milk &)
{
return os<<"Milk";
}
};
//压缩牛奶类
class CondensedMilk
{
public:
friend ostream & operator << (ostream & os,const CondensedMilk &)
{
return os<<"CondensedMilk";
}
};
//蜂蜜类
class Honey
{
friend ostream & operator<<(ostream & os,const Honey &)
{
return os<<"Honey";
}
};
// 饼干类
class Cookies
{
friend ostream & operator<<(ostream & os,const Cookies &)
{
return os<<"Cookies";
}
};
//定义几个访客类
//熊类
class Bear
{
public:
friend ostream & operator<<(ostream & os,const Bear&)
{
return os<<"Big bear";
}
};
//小孩类
class Boy
{
public:
friend ostream & operator << (ostream & os ,const Boy &)
{
return os<<"Little boy";
}
};
//主要traits模板(空模板可以持有所有普通类型)
template <class Guest> class GuestTraits;
//特化的traits类
template<> class GuestTraits<Bear>
{
public:
typedef CondensedMilk beverage_type;
typedef Honey snack_type;
};
template<> class GuestTraits<Boy>
{
public:
typedef Milk beverage_type;
typedef Cookies snack_type;
};
class MixedUpTraits
{
public:
typedef Milk beverage_type;
typedef Honey snack_type;
};
//驱动类
template<class Guest,class traits=GuestTraits<Guest> >
class BearCorner
{
Guest theGuest;
typedef typename traits::beverage_type beverage_type;
typedef typename traits::snack_type snack_type;
beverage_type bev;
snack_type snack;
public:
BearCorner(const Guest & g):theGuest(g){}
void entertain()
{
cout<<"Entertaining "<<theGuest
<< " serving "<<bev
<< " and "<<snack<<endl;
}
};
int main(int argv,char ** args, char ** env)
{
Boy boy;
Bear bear;
BearCorner<Boy> bc1(boy);
bc1.entertain();
BearCorner<Bear> bc2(bear);
bc2.entertain();
BearCorner<Boy,MixedUpTraits> bc3(boy);
bc3.entertain();
return 0;
}
42.特征类组合策略,实现策略类,比如上面的画肖像,可以通过策略类转换为拍肖像等。
43.对象计数的高级实现
#include <iostream>
using namespace std;
template<class T>
class ObjCount
{
static int cnt;
public:
ObjCount(){++cnt;}
ObjCount(const ObjCount<T> & cnt){++cnt;}
~ObjCount(){--cnt;}
static int getCount(){return cnt;}
};
template<class T> int ObjCount<T>::cnt=0;
class TestCnt1:public ObjCount<TestCnt1>{};//父类唯一
class TestCnt2:public ObjCount<TestCnt2>{};//父类唯一
int main(int argv,char ** args, char ** env)
{
TestCnt1 t11,t12;
TestCnt2 t21,t22;
cout<<"TestCnt1::getCount="<<TestCnt1::getCount()<<endl;
cout<<"TestCnt2::getCount="<<TestCnt2::getCount()<<endl;
return 0;
}