#include <iostream>
#include <string>
#include "boost/cast.hpp"
class base1 {
public:
virtual void print() {
std::cout<<"base1::print/n";
}
virtual ~base1() {
}
};
class base2 {
public:
void only_base2() {
std::cout << "only_base2()/n";
}
virtual ~base2() {}
};
class derived : public base1, public base2 {
public:
void print() {
std::cout << "derived::print()/n";
}
void only_here() {
std::cout << "derived::only_here()/n";
}
void only_base2() {
std::cout << "derived::only_base2,Oops, here too!/n";
}
};
int main() {
base1* p1=new derived;
p1->print();
try {
derived* pD=boost::polymorphic_cast<derived*>(p1);
pD->only_here();
pD->only_base2();
base2* pB=boost::polymorphic_cast<base2*>(p1);
pB->only_base2();
}
catch(std::bad_cast& e) {
std::cout << e.what() << '/n';
}
std::cout<<"..../n";
base1 *p2 = new base1;
try {
derived& dog = dynamic_cast<derived&>(*p2);
dog.only_here();
}
catch(exception e ) {
std::cout << e.what() << '/n';
}
delete p1;
}
/*
/GR(启用运行时类型信息)
说明:此选项 (/GR) 添加代码以便在运行时检查对象类型。当指定此选项时,编译器定义 _CPPRTTI 预处理器宏。默认情况下,此选项被清除 (/GR–)。
在 Visual Studio 开发环境中设置此编译器选项
打开此项目的“属性页”对话框。
单击“C/C++”文件夹。
单击“语言”属性页。
修改“启用运行时类型信息”属性。
*/
/*Output:
derived::print()
derived::only_here()
derived::only_base2,Oops, here too!
only_base2()
....
Bad dynamic_cast!
*/
dynamic_cast提供了两种转换方式,把基类指针转换成派生类指针,或者把指向基类的左值转换成派生类的引用。
std::cout<<"..../n";
base1 *p2 = new base1;
try {
derived* dog = dynamic_cast<derived*>(p2);
if ( dog != 0)
dog->only_here();
else
std::cout<<"fail"<<std::endl;
}
catch(exception e ) {
std::cout << e.what() << '/n';
}
Output: fail
===========
Even without polymorphic_cast, if people know about the different ways that dynamic_cast works, it is still possible to achieve the same level of safety, as is shown in the following example.
void failure_is_error(base1* p) {
try {
some_other_class& soc=dynamic_cast<some_other_class&>(*p);
// Use soc
}
catch(std::bad_cast& e) {
std::cout << e.what() << '/n';
}
}
void failure_is_ok(base1* p) {
if (some_other_class* psoc=
dynamic_cast<some_other_class*>(p)) {
// Use psoc
}
}
In this example, the pointer p is dereferenced[5] and the target type of the conversion is a reference to some_other_class. This invokes the throwing version of dynamic_cast. The second part of the example uses the non-throwing version by converting to a pointer type.
ps:
template <class Target, class Source>
inline Target polymorphic_downcast(Source* x BOOST_EXPLICIT_DEFAULT_TARGET)
{
assert( dynamic_cast<Target>(x) == x ); // detect logic error
return static_cast<Target>(x);
}
polymorphic_downcast tests the cast with dynamic_cast, but only in debug builds; it then uses static_cast to perform the conversion.
static_cast is faster but unsafe!!