不能因为类不是多态而沮丧?

Posted

技术标签:

【中文标题】不能因为类不是多态而沮丧?【英文标题】:Can't downcast because class is not polymorphic? 【发布时间】:2012-01-18 04:28:18 【问题描述】:

是否可以在没有虚拟方法的情况下进行继承?编译器说下面的代码不是多态的。

例子:

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? (***.com/questions/332030/…) 【参考方案1】:

语法错误是不可容忍的,你不能dynamic_cast 一个非多态类型。 static_cast 是您在这种情况下使用的转换,如果您知道它实际上是目标类型的对象。

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

dynamic_cast 只能用于指针或引用转换的情况下,除了编译时检查外,它还会进行额外的运行时检查以确保转换是否合法。它要求所讨论的类至少有 1 个虚拟方法,这允许编译器(如果它支持 RTTI)执行此附加检查。但是,如果该类型没有任何虚方法,则不能使用。

最简单的情况,如果你像这样传递指针,可能是值得的,就是考虑将基类的析构函数设为虚拟。除了允许您使用动态转换之外,它还允许在删除基类指针时调用适当的析构函数。

【讨论】:

【参考方案2】:

run-time type information (RTTI) 至少需要一个类中的虚拟方法才能成功应用 dynamic_cast 运算符。

【讨论】:

【参考方案3】:

只需将 A 析构函数设为虚拟(出于安全考虑,总是对任何类执行此操作)。

【讨论】:

不是针对任何类,而是针对打算作为基类的类 这不是不安全的吗,因为将调用子析构函数而不是父析构函数?程序员可能会忘记调用 BaseClass::~BaseClass() 并且会被搞砸,因为父部分不会被破坏。 @Kari,父(基)析构函数在子析构函数之后自动调用。无需显式调用此析构函数。【参考方案4】:

是的,不允许用于非多态类型的 dynamic_cast。基类应至少有一个虚方法。只有这样才能将该类称为多态。

这篇文章解释了一个类似的例子:http://www.cplusplus.com/doc/tutorial/typecasting/

【讨论】:

【参考方案5】:
A a;
B *b = dynamic_cast<B*>(a)

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

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

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

【讨论】:

以上是关于不能因为类不是多态而沮丧?的主要内容,如果未能解决你的问题,请参考以下文章

抽象类和抽象方法接口和多态

在C ++中使用多态而不是继承的实际优势[关闭]

继承多态接口

试图用多态来沮丧,出了啥问题?

JAVA面向对象3---多态

面向对象---多态-抽象