由于类不具有多态性,无法进行向下转型?

62

有没有可能继承一个类但不使用虚函数?编译器提示以下代码不是多态的。

示例:

class A {
public:
    int a;
    int getA(){return a;};
}


class B : public A {
public:
    int b;
    int getB(){return b;};
}

在另一个类中,我们尝试将一个 A 对象向下转换为一个 B 对象:

 A *a = ...;
 B *b = dynamic_cast<B*>(a)

但是这会导致以下编译时错误:

 cannot dynamic_cast ... (source type is not polymorphic)

除了已接受的答案外,您可能还想查看这个问题:何时应使用 static_cast、dynamic_cast 和 reinterpret_cast?(https://dev59.com/IXRC5IYBdhLWcg3wVvct) - yasouser
5个回答

92

除了语法错误外,你不能对非多态类型进行 dynamic_cast。在这种情况下,如果你知道它实际上是目标类型的对象,你将使用 static_cast

原因是: static_cast 基本上让编译器在编译时执行一个检查“输入是否可以转换为输出?” 它可以用于指针(或引用)继承层次结构向上或向下转换的情况。但该检查仅在编译时进行,并且编译器假定您知道自己在做什么。

dynamic_cast 只能用于指针或引用转换的情况,并且除了编译时检查外,它还会执行额外的运行时检查以确保强制转换是合法的。它要求相应的类至少有一个虚函数,这允许编译器(如果支持 RTTI)执行此额外的检查。然而,如果所涉及的类型没有任何虚函数,则无法使用 dynamic_cast。

最简单的情况,如果你像这样传递指针,那么考虑将基类的析构函数声明为虚函数。除了使你能够使用 dynamic_cast 外,它还允许在删除基类指针时调用正确的析构函数。


38

在一个类中至少需要一个虚方法,才能成功应用 dynamic_cast 运算符进行运行时类型信息(RTTI)转换。


22

仅需将析构函数设为虚函数(对于任何类都应该这样做,以提高安全性)。


12
不是为了任何类别,而是为了那些打算作为基类的类。 - ParokshaX
这样做不安全,因为会调用子类的析构函数而不是父类的析构函数。程序员可能会忘记调用BaseClass ::〜BaseClass()并且会出现问题,因为父类部分不会被销毁。 - Kari
1
@Kari,当子类的析构函数执行完毕后,父类(基类)的析构函数会自动被调用。因此无需显式地调用该析构函数。 - m7913d

6

4
A a;
B *b = dynamic_cast<B*>(a)

这里a是一个对象,b是一个指针。

实际上,在C++中允许向上转型和向下转型。但使用向下转型时需要注意以下2点:

  1. 超类至少应该有一个虚方法。
  2. 由于超类比子类“小”,所以应该谨慎使用内存对象。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接