c++ - 使用 dynamic_cast 而不是传统的多态有什么优势?

标签 c++ polymorphism dynamic-cast

我们可以使用多态(继承+虚函数)来泛化不同的类型在一个共同的基类型下,然后引用不同的对象,就好像它们是相同的类型一样。

使用 dynamic_cast 似乎是完全相反的方法,因为本质上我们在决定要采取什么操作之前检查对象的特定类型。

是否有任何已知的例子说明某些东西不能像使用 dynamic_cast 那样容易地使用传统多态性来实现?

最佳答案

每当您发现自己想要基类中的成员函数(如“IsConcreteX”)时(编辑:或者更准确地说,是像“ConcreteX *GetConcreteX”这样的函数),您基本上是在实现自己的dynamic_cast。例如:

class Movie
{
    // ...
    virtual bool IsActionMovie() const = 0; 
};

class ActionMovie : public Movie
{
    // ...
    virtual bool IsActionMovie() const { return true; }
};

class ComedyMovie : public Movie
{
    // ...
    virtual bool IsActionMovie() const { return false; }
};


void f(Movie const &movie)
{
    if (movie.IsActionMovie())
    {
        // ...
    }
}

这可能看起来比 dynamic_cast 更干净,但仔细检查后,您很快就会意识到除了“邪恶的”dynamic_cast 不再出现在您的代码中(前提是您使用的不是未实现 dynamic_cast 的古老编译器!:))。更糟糕的是 - “自行编写的动态转换”方法冗长、容易出错且重复,而 dynamic_cast 将在类定义中没有任何额外代码的情况下工作得很好。

所以真正的问题应该是在某些情况下是否基类知 Prop 体的派生类是有意义的。答案是:通常不会,但你肯定会遇到这样的情况。

以非常抽象的方式思考软件的一个组件,该组件将对象从一部分 (A) 传输到另一部分 (B)。这些对象是 Class1Class2 类型,Class2 is-a Class1 .

Class1
  ^
  |
  |
Class2


A - - - - - - - -> B
    (objects)
但是,

B 仅对 Class2 有一些特殊处理。 B 可能是系统中完全不同的部分,由不同的人编写,或者是遗留代码。在这种情况下,您希望在不进行任何修改的情况下重用 A 到 B 的通信,并且您可能也无法修改 B。因此,明确询问您在该行的另一端处理的是 Class1 还是 Class2 对象可能是有意义的。

void receiveDataInB(Class1 &object)
{
    normalHandlingForClass1AndAnySubclass(object);
    if (typeid(object) == typeid(Class2))
    {
        additionalSpecialHandlingForClass2(dynamic_cast<Class2 &>(object));
    }
}

这是一个不使用 typeid 的替代版本:

void receiveDataInB(Class1 &object)
{
    normalHandlingForClass1AndAnySubclass(object);
    Class2 *ptr = dynamic_cast<Class2 *>(&object);
    if (ptr != 0)
    {
        additionalSpecialHandlingForClass2(*ptr);
    }
}

如果 Class2 不是叶类(即如果可能有进一步派生自它的类),这可能更可取。

最后,它通常归结为您是从一开始就设计一个包含所有部分的整个系统,还是必须在后期修改或调整其中的部分。但是,如果您发现自己遇到了上述问题,您可能会开始欣赏 dynamic_cast 作为在正确情况下完成正确工作的正确工具。

关于c++ - 使用 dynamic_cast 而不是传统的多态有什么优势?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22282160/

相关文章:

c++ - 像素距离泛光填充

c++ - 为什么在使用 boost::function 调用函数对象时不需要类实例

java - 这个方法是重载、重写还是无?

c++ - 如何在 if 语句中使用 dynamic_cast

c++ - 构造函数和复制构造函数的顺序

c++ - 对话窗口在完成之前关闭(已接受);

c++ - 将基类动态转换为派生对象

C++动态向下转换为具有模板模板参数的类模板是类模板或别名模板

c++ - 基类中的非虚析构函数,但派生类中的虚析构函数导致段错误

c++ - 继承和内联?