转载:http://www.weixueyuan.net/view/6377.html
在C++中,编译期的类型转换有可能会在运行时出现错误,特别是涉及到类对象的指针或引用操作时,更容易产生错误。Dynamic_cast操作符则可以在运行期对可能产生问题的类型转换进行测试。
例1:
- #include<iostream>
- using namespace std;
- class base
- {
- public :
- void m(){cout<<"m"<<endl;}
- };
- class derived : public base
- {
- public:
- void f(){cout<<"f"<<endl;}
- };
- int main()
- {
- derived * p;
- p = new base;
- p = static_cast<derived *>(new base);
- p->m();
- p->f();
- return 0;
- }
产生这种运行期的错误原因在于static_cast强制类型转换时并不具有保证类型安全的功能,而C++提供的dynamic_cast却能解决这一问题,dynamic_cast可以在程序运行时检测类型转换是否类型安全。当然dynamic_cast使用起来也是有条件的,它要求所转换的操作数必须包含多态类类型(即至少包含一个虚函数的类)。
例2:
- #include<iostream>
- using namespace std;
- class base
- {
- public :
- void m(){cout<<"m"<<endl;}
- };
- class derived : public base
- {
- public:
- void f(){cout<<"f"<<endl;}
- };
- int main()
- {
- derived * p;
- p = new base;
- p = dynamic_cast<derived *>(new base);
- p->m();
- p->f();
- return 0;
- }
dynamic_cast还要求<>内部所描述的目标类型必须为指针或引用。如例3所示,如果我们将例2中的主函数换成例3的形式,这也是无法通过编译的。
例3:
- int main()
- {
- base b;
- dynamic_cast<derived>(b);
- return 0;
- }
例4:
#include<iostream> using namespace std;class base { public :virtual void m(){cout<<"m"<<endl;} };class derived : public base { public:void f(){cout<<"f"<<endl;} };int main() {derived * p;p = dynamic_cast<derived *>(new base);if(p){p->m();p->f(); }elsecout<<"Convert not safe!"<<endl;return 0; }在本例中通过dynamic_cast来初始化指针p,在初始化过程中dynamic_cast会检测操作数new base转换为目标类型derived *是否能保证类型安全,如果类型安全则将new base结果赋给p指针,否则返回0,也即false。而本例中是要用基类对象地址去初始化派生类指针,这显然是无法保证类型安全的,因此p最后得到的返回值是0。在主函数中经过判断语句,最终程序输出“Convert not safe!”。
Dynamic_cast转换有自己的规则,下面将通过示例来介绍转换规则。
例4:
- #include<iostream>
- using namespace std;
- class base
- {
- public :
- virtual void m(){cout<<"m"<<endl;}
- };
- class derived : public base
- {
- public:
- virtual void f(){cout<<"f"<<endl;}
- };
- int main()
- {
- derived * d;
- d = dynamic_cast<derived *>(new base);
- if(d)
- {
- cout<<"Base to Derived is ok"<<endl;
- delete d;
- }
- else
- cout<<"Base to Derived is error"<<endl;
- base * b;
- b = dynamic_cast<base *>(new derived);
- if(b)
- {
- cout<<"Derived to Base is ok"<<endl;
- delete b;
- }
- else
- cout<<"Derived to Base is error"<<endl;
- return 0;
- }
Base to Derived is error
Derived to Base is ok
从结果可以看出从不能将指向基类对象的指针转换为指向派生类对象的指针,但是可以将指向派生类对象的指针转换为指向基类对象的指针。
例5:
- #include<iostream>
- using namespace std;
- class A
- {
- public :
- virtual void m(){cout<<"m"<<endl;}
- };
- class B
- {
- public:
- virtual void f(){cout<<"f"<<endl;}
- };
- int main()
- {
- A * a;
- a = dynamic_cast<A *>(new B);
- if(a)
- {
- cout<<"B to A is ok"<<endl;
- delete a;
- }
- else
- cout<<"B to A is error"<<endl;
- B * b;
- b = dynamic_cast<B *>(new A);
- if(b)
- {
- cout<<"A to B is ok"<<endl;
- delete b;
- }
- else
- cout<<"A to B is error"<<endl;
- return 0;
- }
B to A is error
A to B is error
从程序运行结果不难看出,任意两个不相关的多态类类型之间的转换也是不能进行的。
总结一下dynamic_cast转换规则,只允许指向派生类对象的指针转换为指向基类对象的指针。
C++提供的两个类型转换操作符static_cast和dynamic_cast,static_cast可以用于任何类型的强制类型转换,但是它不保证转换过程中的类型安全,dynamic_cast只能用于多态类类型的转换,而且要求转换的目的类型必须为指针或引用,并且它可以保证转换过程中类型安全。