一 typeid与dynamic_cast
1)RTTI, Runtime Type Identification (RTTI) or Run-time type information (RTTI),表示在运行时动态决定变量的类型,来调用正确的虚函数。 RTTI在VS2008中默认为关闭,可以通过修改编译选项Enable Run-Time Type Info 为 Yes,来启用RTTI,只有当启动RTTI时,用来RTTI功能的typeid和dynamic_cast才能正常工作。
2)type_info,用来描述类型信息。type_info存储了它所描述的类型的名字。RTTI就是使用type_info来实现的。type_info的定义如下:
class type_info {
public:
virtual ~type_info();
bool operator== (const type_info& rhs) const;
bool operator!= (const type_info& rhs) const;
bool before (const type_info& rhs) const;
const char* name() const;
private:
type_info (const type_info& rhs);
type_info& operator= (const type_info& rhs);
};
问题:RTTI怎么实现那?对象,type_info,虚函数怎么关联那?《深入C++对象模型》中说在虚函数表的开始存储了类型信息,但是实际的VS2008中好像并没有此信息,请高人指点哦!
3)typeid,在运行时获得对象的类型,typeid()返回的是const type_info&,而 type_info包含了对象真实类型的名字。typeid能被用来获取一个引用对象或指针指向的对象的运行时的真实类型。当然如果对象为null或编译时没有使用/GR的话,typeid的会抛出异常bad_typeid exception或__non_rtti_object。实例代码:
class Base
{
public:
virtual void f(){ }
};
class Derived : public Base
{
public:
void f2() {}
};
void main ()
{
Base *pB = new Derived();
const type_info& t = typeid(*pB);cout <<t.name() << endl;
delete pB;
Derived d;
Base& b = d;
cout << typeid(b).name() << endl;
}
运行结果:
4)dynamic_cast,用来运行时的类型转化,需要/GR来正确运行。
适用:
第一,用于所有的父子和兄弟间指针和引用的转化,有类型安全检查;
第二,对指针类型,如果不成功,返回NULL,对引用类型,如果不成功,则抛出异常;
第三,类型必须要有虚函数,且打开/GR编译选项,否则不能使用dynamic_cast。
实例代码:
class AA
{
public:
virtual void do_sth(){ std::cout<<"AA\n"; }
};
class BB
{
public:
virtual void do_sth(){ std::cout<<"BB\n"; }
};
class CC : public AA, public BB
{
public:
virtual void do_sth(){ std::cout<<"CC\n"; }
};
void DynamicCastTest()
{
AA *pA = new CC;
BB *pB = dynamic_cast<BB*>(pA);
if(pB != NULL)
cout << "cast successful!" << endl;
CC *pC = dynamic_cast<CC*>(pA);
if(pC != NULL)
cout << "cast successful!" << endl;
}
二 其他cast
1)隐式转化,不需要任何操作符,转化被自动执行,当一个值被赋值到它所兼容的类型时。
适用:
第一,内置基本类型的兼容转化;
第二, 子类指针,引用向父类的转化;
实例:
class A
{
public:
virtual ~A(){}
};
class B : public A
{
};
void ImplicitCast()
{
short a = 2000;
int b;
b = a;
double d = 10.05;
int i;
i = d;
int j = 75;
char c;
c = j;
A* pA = new B();
}
2)强制类型转化,即我们常说的C风格的类型转化,基本上可以用于所有的转化,但是没有意义的转化除外,但是父子类,兄弟间的转化没有类型检查可能导致运行是错误。
适用:
第一,基本类型转化;
第二,void*到其他指针的转化;
第三,去除const;
第五,函数指针的转化;
第六,父子类转化,但是多重继承和兄弟转化,可能有运行时错误,没有类型检查;
第七,任何两个类,但是没有实际意义,运行可能出错;
第八,不能用于没有意义的转化,严厉禁止,例如,你不能用static_cast象用C风格的类型转换一样把struct转换成int类型,或者把double类型转换成指针类型;
第九,在C++一般更推荐新加的static_cast,const_cast,dynamic_cast和reinterpret_cast转化方式;
实例:
class CDummy
{
public:
CDummy(float x, float y)
{
i = x;
j = y;
}
private:
float i,j;
};
class CAddition
{
public:
CAddition (int a, int b) { x=a; y=b; }
int result() { return x+y;}

