复习——dynamic_cast(RTTI)

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*

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值