废话不多说,直接给结论:
class base
{
public:
base(){}
virtual ~base(){}
int m_a;
virtual void setA()
{
m_a = 0;
}
};
class A : public base
{
public:
A(){}
virtual ~A(){}
virtual void setA()
{
m_a = 1;
}
virtual void setAA()
{
m_a = 2;
}
};
情况1:
base newBase = new base;
A* newA = dynamic_cast< A* > ( newBase ); //返回值为NULL,编译无问题,但实际根本不能用
newA->setAA(); //报错,因为newA=NULL
结论1:
基类指针强制变换为子类指针后,若基类指针指向的是一个基类实体,那么虽然编译没有问题,可完全无法实际使用,即转换失败!
情况2:
base newBase = new A;
A* newA = dynamic_cast< A* > ( newBase ); //OK
newA->setAA(); //OK
结论2:
基类指针强制变换为子类指针后,若基类指针指向的是一个子类实体,转换成功,调用子类新增的成员函数没有问题!
情况3:
base newBase = new A;
A* newA = dynamic_cast< A* > ( newBase ); //OK
newA->setA(); //OK
结论3:
基类指针强制变换为子类指针后,若基类指针指向的是一个子类实体,转换成功,调用子类虚函数(在这个实例里实际就是重构)没有问题,不会发生调用错函数的问题!
情况4:
A* newA = new A;
base* newbase = dynamic_cast< base* > ( newA ); //OK
newbase->setA(); //OK,由于是虚函数所以执行的是A中的setA();
结论4:
伟大的虚函数功能并没有因为强制转换而消失!再次膜拜伟大的RTTI!
情况5:
A* newA = new A;
base* newbase = dynamic_cast< base* > ( newA );
newbase->setAA(); //成员函数不存在,无法编译通过
结论5:
不解释。
最后的结论:
在继承体系中,上行转换(子类->基类)dynamic_cast与static_cast功能完全一样,有效且安全;
下行转换(基类->子类)则必须视基类实际指向的对象类型而定,只有基类指向的对象为子类类型时才有效且安全!
多日后再思考,又出现一个新想法,尝试:
class subBase
{public:
subBase(){}
virtual ~subBase(){}
int m_b;
virtual void setB()
{
m_b = 10;
}
};
class multiA : public base, public subBase
{
public:
multiA(){};
virtual ~multiA(){};
virtual void setA()
{
m_a = 3;
}
virtual void setB()
{
m_b = 11;
}
};
情况6:
base* newbase = new multiA ;
subBase* newsubbase = dynamic_cast< subBase* > ( newbase );
newsubbase->setB(); //OK m_b = 11;
结论6:
在多重继承的情况下,只要指针实际指向对象为子类对象,那么对于指向子类对象的基类指针,可以使用dynamic_cast在不同基类之间相互转换,转换后对应基类的虚函数特性得到保存。
|