Q1:保证安全的基类到派生类的向下转换操作
• 支持安全的类型转换对多态类而言,需要在执行期判断指针所指对象的真实类型,因此,会引入额外的空间与时间开销:
○ 空间开销:存储类型信息,通常是一个指针,指向某个类型信息的节点(该指针放置在虚函数表的第一个表项中)
○ 时间开销:在执行其决定其类型
• 区别一个类是否具有多态性,是根据其是否内含虚函数来进行判断。(注:析构函数是唯一不能重载的成员函数
)
Q2:保证安全的动态转换
• dynamic_cast 运算符可以在执行期决定真正的类型,对指针对象而言,如果该操作是安全的,就会传回被适当转换过的指针,如果不安全,就传回0
• 考虑 dynamic_cast 的真正成本
Eg:
//class B : public A{};
void example(A * ap)
{
if(B * bp = dynamic_cast<B*>(ap))
{//…}
else
{//…}
}
以上式为例,编译器会为 B* 产生一个类型描述器,并通过 ap 所指类对象的类型则通过 vptr 取得,取得方式如下:
((type_info*)(ap->vptr[0]))->_type_descriptor; //取得 ap 所指类对象的类型描述器
type_info 是 C++ 标准定义的类型描述器的类名称,通过 vptr 取得 ap 所指对象的类型描述器,将两个类型描述器进行比较,即可判断该转换是否安全
Q3:引用并不是指针
• 对一个类指针施行 dynamic_cast ,会获得该指针值或者0:
• 如果传回指针,表示该转换操作安全
• 如果传回0,表示该转换错误。0表示该指针并未指向任何对象
• 对引用而言,不能对一个引用赋值为0,表示其并未引用任何对象!!!!因为当将 0 赋值给引用对象时,将会产生一个临时对象,该对象的初值是0,该引用会被设为此临时对象的别名。
• 对一个引用施行 dynamic_cast,会成功或者抛出一个 bad_cast 异常:
• 若未抛出异常,则引用转换操作安全
• 若抛出异常,则该引用转换不安全
• 合适的引用转换操作例子。将上述程序例子改为:
Eg:
void example(A & a)
{
try{
B & b = dynamic_cast<B&>(a);
}
catch (bad_cast b)
{
//…
}
}
Q4:Typeid 运算符
• typeid运算符传回一个 const reference,其类型为 type_info
• type_info 类对象支持的操作:==,!=,before(),name(),VS 还提供(raw_name())
• type_info 的默认构造函数,复制构造函数,赋值操作符函数均是私有函数,因此, type_info 对象不支持复制