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会导致性能下降。

上一篇:使用 mybatisPlus 的 dynamic datasource 配置多数据源中的问题


下一篇:Mysql多数据源Springboot+mybatis+druid+dynamic-datasource