Learn C++学习笔记:第十二章—动态转换 dynamic_cast

多态允许我们把指向基类的指针可以访问派生类的内容,但是假如我们想访问的派生类中的函数不是重写的基类的虚函数,而是派生类自己的函数呢?
上例子更清楚明白一点:

#include <iostream>
#include <string>
 
class Base
{
protected:
	int m_value;
 
public:
	Base(int value)
		: m_value(value)
	{
	}
	
	virtual ~Base() {}
};
 
class Derived : public Base
{
protected:
	std::string m_name;
 
public:
	Derived(int value, std::string name)
		: Base(value), m_name(name)
	{
	}
 
	const std::string& getName() const { return m_name; }
};
 
Base* getObject(bool bReturnDerived)
{
	if (bReturnDerived)
		return new Derived(1, "Apple");
	else
		return new Base(2);
}
 
int main()
{
	Base *b = getObject(true);
 
	// how do we print the Derived object's name here, having only a Base pointer?
 
	delete b;
 
	return 0;
}

由于返回的指针类型一直都是基类型的指针,在指针指向Derived对象的情况下,我们怎么调用Derived :: getName()呢?
这时候就是:
dynamic_cast
C ++提供了一个名为dynamic_cast的强制转换运算符,可用于此目的。尽管动态类型转换具有一些不同的功能,但到目前为止,动态类型转换最常见的用途是将基类指针转换为派生类指针。此过程称为向下转换。

改写函数为:

int main()
{
	Base *b = getObject(true);
 
        Derived *d = dynamic_cast<Derived*>(b); // use dynamic cast to convert Base pointer into Derived pointer
 
        std::cout << "The name of the Derived is: " << d->getName() << '\n';
 
	delete b;
 
	return 0;
}

将打印:

The name of the Derived is: Apple

防止转换失败

但是,我们做出了一个非常危险的假设:b指向派生对象。如果b没有指向派生对象怎么办?通过将getObject()的参数从true更改为false,可以轻松地进行测试。在这种情况下,getObject()将返回指向基础对象的基础指针。当我们尝试将其动态转换为“派生”时,它将失败,因为无法进行转换。

如果dynamic_cast失败,则转换结果将为空指针。

因为我们没有检查空指针结果,所以我们访问d-> getName(),它将尝试取消引用空指针,从而导致未定义的行为(可能是崩溃)。

为了使该程序安全,我们需要确保dynamic_cast的结果实际上是成功的:

int main()
{
	Base *b = getObject(true);
 
        Derived *d = dynamic_cast<Derived*>(b); // use dynamic cast to convert Base pointer into Derived pointer
 
        if (d) // make sure d is non-null
            std::cout << "The name of the Derived is: " << d->getName() << '\n';
 
	delete b;
 
	return 0;
}

①始终通过检查空指针结果来确保动态转换真正成功。
②请注意,由于dynamic_cast在运行时会进行一些一致性检查(以确保可以进行转换),因此使用dynamic_cast会导致性能下降。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值