C++ Dynamic_cast - 多态要求和向下转型
在下面的代码中,在情况 1 中构造 obj 时,我们也构造了一个派生类对象,但它的成员函数对于 obj 来说是无法访问的。因此,在向下转换时(即在情况 2 中),使用 obj 作为源,我们已经在其中构造了派生的。为什么 obj
需要多态?
如果我对上面的描述感到困惑,为什么在向上转换时 obj
不需要是多态的,但在向下转换时确实在使用 dynamic_cast 时需要是多态的?
class base
{
public:
base()
{
cout<< " \n base constructor \n";
}
};
class derived : public base
{
public:
derived()
{
cout << " \n derived constructor \n";
}
};
base *obj = dynamic_cast<base*> (new derived); // case 1: explicitly upcasting
derived *OBJ = dynamic_cast<derived*> (obj); // case 2: error
In the following code, while constructing obj
in case 1, we construct a derived
class object too, but its member functions are just inaccessible to obj
. So while downcasting (i.e., in case 2), using obj
as source, we have the constructed derived
in it already. Why would obj
need to be polymorphic?
If I confused you with my above description, why doesn't obj
need to be polymorphic when upcasting, but while downcasting it does need to be polymorphic while using dynamic_cast
?
class base
{
public:
base()
{
cout<< " \n base constructor \n";
}
};
class derived : public base
{
public:
derived()
{
cout << " \n derived constructor \n";
}
};
base *obj = dynamic_cast<base*> (new derived); // case 1: explicitly upcasting
derived *OBJ = dynamic_cast<derived*> (obj); // case 2: error
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
为了让dynamic_cast工作,对象需要是多态的。原因是 dynamic_cast 需要在某个地方存储用于执行转换的类型信息,它通过将信息与类的 vtable 一起存储来实现这一点。为了有一个虚函数表,您需要将至少一个方法设为虚拟。
解决这个问题最简单的方法是将基类析构函数标记为虚拟。
向上转换(即派生到基数)不需要强制转换,因为编译器能够检查强制转换在编译时是否有效。然而,当情绪低落时,情况却并非如此。
In order for dynamic_cast to work the object needs to be polymorphic. The reason for this is that dynamic_cast needs somewhere to store the type information that is will use to perform the cast, and it does this by storing the information alongside the vtable for the class. In order for there to be a vtable you need to make at least one of your methods virtual.
The easiest way around this is to flag the base class destructor as virtual.
Upcasting (ie derived to base) doesn't needs a cast as the compiler is able to check that the cast would work at compile time. However, the same isn't true when downcasting.
从 5.2.7/1 [expr.dynamic.cast] 开始:
该标准甚至提供了以下示例,说明多态类型要求并不代表派生到基类的转换:
From 5.2.7/1 [expr.dynamic.cast] :
The standard even provides the following example which illustrates that the polymorphic type requirement does not stand for derived to base conversion :
在上面的例子中,大多数编译器会通过检查b的vtable指针是否指向派生类D的vtable来实现动态转换。
如果是,则简单地返回 b 的地址作为返回值,否则返回 nullptr。
这就是执行动态转换时幕后可能发生的情况:-
现在,如果该类不是多态的,则编译器无法确定 pCar 是否指向本田汽车或丰田汽车。请注意,这只是实现dynamic_cast 的方法之一,因为C++ 标准没有谈论vtable。
In the above example most compilers would implement dynamic cast by checking whether the vtable pointer of b points to the vtable of the derived class D or not.
If yes, it simply returns the address of b as the return value otherwise it returns a nullptr.
This is what possibly goes on behind the scenes when a dynamic cast executes :-
Now, if the class is not polymorphic, there is no way for the compiler to find whether pCar is pointing to honda or toyota car. Note that this is just one of the ways to implement dynamic_cast as the C++ standard does not talk anything about vtables.
Dynamic_cast
转化为派生指针。如果基地
指针不指向以下对象
派生的类型,它返回
进入派生参考。如果
引用未指向对象
派生的,它抛出
std::bad_cast。
相当于 static_cast,因为它
检查对象是否指向
确实是派生类型。
您必须阅读有关 Dynamic_cast 的更多信息(带有示例)那里。
Dynamic_cast
into a derived pointer. If the base
pointer doesn't point to an object of
the type of the derived, it returns
into a derived reference. If the
reference isn't pointing to an object
of the derived, it throws
std::bad_cast.
equivalent to static_cast, in that it
checks whether the object pointed to
really is of the derived type.
You must read more about Dynamic_cast (with example) there.