dynamic_cast
属于RTTI,运行时类型识别的一个内容。
例子1
直接看代码:
代码1:
class Base {
public:
Base() :b(1) {}
virtual void foo() {}
int b;
};
class Derived :public Base
{
public:
Derived() :d(2), Base() {}
int d;
};
void fun(Base*pb)
{
Derived*pd1 = static_cast<Derived*>(pb);//把基类对象指针下行转换为派生类对象指针
cout << pd1->b << endl;
cout << pd1->d << endl;
//Derived*pd2 = dynamic_cast<Derived*>(pb);//把基类对象指针下行转换为派生类对象指针
//cout << pd2->b << endl;
//cout << pd2->d << endl;
}
int main()
{
Base*p1 = new Derived();//基类指针指向派生类的对象
fun(p1);
Base*p2 = new Base();//基类指针指向基类的对象
fun(p2);
system("pause");
return 0;
}
代码2:
class Base {
public:
Base() :b(1) {}
virtual void foo() {}
int b;
};
class Derived :public Base
{
public:
Derived() :d(2), Base() {}
int d;
};
void fun(Base*pb)
{
//Derived*pd1 = static_cast<Derived*>(pb);//把基类对象指针下行转换为派生类对象指针
//cout << pd1->b << endl;
//cout << pd1->d << endl;
Derived*pd2 = dynamic_cast<Derived*>(pb);//把基类对象指针下行转换为派生类对象指针
cout << pd2->b << endl;
cout << pd2->d << endl;
}
int main()
{
Base*p1 = new Derived();//基类指针指向派生类的对象
fun(p1);
Base*p2 = new Base();//基类指针指向基类的对象
fun(p2);
system("pause");
return 0;
}
这是因为使用static_cast
将基类指针或引用下行转换为派生类的指针或引用时,由于没有进行动态类型检查,虽然下行转换能成功,但是不安全。系统不知道转换后的派生类指针是否真的指向了一个派生类的对象。
而使用dynamic_cast
将基类指针或引用下行转换为派生类的指针或引用时,系统就会检查转换后的派生类指针是否真的指向了一个派生类的对象,如果转换后的派生类指针没有指向一个派生类的对象(比如指向了一个基类的对象),那么运行时触发中断(对于指针返回NULL,对于引用则抛出异常)。
注意点:dynamic_cast
涉及运行时类型检查。dynamic_cast
运行时类型检查需要运行时类型信息,而这个信息储存在类的虚函数表中,只有定义了虚函数的类才有虚函数表,对没有定义虚函数的类使用dynamic_cast
会导致编译错误。
例子2
class Base1 {
public:
virtual void f1() { cout << "Base1::f1" << endl; }
};
class Base2 {
public:
virtual void f2() { cout << "Base2::f2" << endl; }
};
class Derived :public Base1, public Base2
{
public:
void f1() { cout << "Derived::f1" << endl; }
void f2() { cout << "Derived::f2" << endl; }
};
int main()
{
Base1*pb1 = new Derived();//基类Base1的指针指向派生类的对象
Derived *pd1 = static_cast<Derived*>(pb1);//正确
Derived *pd1 = dynamic_cast<Derived*>(pb1);//正确
//接下来是关键的地方,即要将Base1*转化为Base2*
//Base2*pb2= static_cast<Base2*>(pb1);//错误
Base2*pb2 = dynamic_cast<Base2*>(pb1);//正确(法1)
Base2*pb2 = static_cast<Base2*>(static_cast<Derived*>(pb1));//正确(法2)
system("pause");
return 0;
}
这个例子的关键在于如何将Base1*
转化为Base2*
,这里给出两种方法:
法1:如果要直接转化,那么必须用dynamic_cast
;
法2:因为Derived*
、Base1*
、Base2*
之间存在隐式转换关系,所以先把Base1*
隐式转化为Derived*
,再把Derived*
隐式转化为Base2*
。