比较C ++中的多态基本类型而不使用RTTI [英] Comparing Polymorphic Base Types in C++ without RTTI

查看:141
本文介绍了比较C ++中的多态基本类型而不使用RTTI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些指向一个基本类型的形状。我想使用==运算符来比较这些对象。如果对象是不同的派生类型,==运算符显然返回false。如果它们是相同的派生类型,那么派生类型的成员应该进行比较。

I have some pointers to a base type of Shape. I want to compare these objects using the == operator. The == operator should obviously return false if the objects are of different derived type. If they are of the same derived type however the members of the derived type should then be compared.

我已经知道,使用C ++ RTTI是不好的做法,用于罕见和基本情况。至于我可以看到这个问题不能一般解决不使用RTTI。每个重载的==运算符都必须检查typeid,如果它们是相同的,执行dynamic_cast并比较成员。这似乎是一个普遍的需要。这个问题是否有某种成语?

I have read that using the C++ RTTI is bad practice and should only be used in rare and essential circumstances. As far as I can see this problem cannot be generally solved without using the RTTI. Each overloaded == operator would have to check the typeid, and if they are the same perform a dynamic_cast and compare the members. This seems like a common need. Is there some kind of idiom for this problem?

#include <iostream>
using namespace std;

class Shape {
  public:
    Shape() {}
    virtual ~Shape() {}
    virtual void draw() = 0;

    virtual bool operator == (const Shape &Other) const = 0;
};

class Circle : public Shape {
  public:
    Circle() {}
    virtual ~Circle() {}
    virtual void draw() { cout << "Circle"; }

    virtual bool operator == (const Shape &Other) const {
      // If Shape is a Circle then compare radii
    }

  private:
    int radius;
};

class Rectangle : public Shape {
  public:
    Rectangle() {}
    virtual ~Rectangle() {}
    virtual void draw() { cout << "Rectangle"; }

    virtual bool operator == (const Shape &Other) const {
      // If Shape is a Rectangle then compare width and height
    }

  private:
    int width;
    int height;
};

int main() {
  Circle circle;
  Rectangle rectangle;

  Shape *Shape1 = &circle;
  Shape *Shape2 = &rectangle;

  (*Shape1) == (*Shape2); // Calls Circle ==
  (*Shape2) == (*Shape1); // Calls Rectangle ==
}


推荐答案

使用RTTI。
使用 typeid ,但使用 static_cast ,而不是 dynamic_cast

Use the RTTI. Use typeid, but use static_cast rather than dynamic_cast.

从设计的角度来看,我认为这正是RTTI的目的,任何替代解决方案都必然会是丑陋的。 / p>

From a design point of view, I'd say that this is exactly what RTTI is for, any alternative solutions will, by necessity, be uglier.

virtual bool operator == (const Shape &Other) const {
    if(typeid(Other) == typeid(*this))
    {
        const Circle& other = static_cast<const Circle&>(Other);
        // ...
    }
    else
        return false;
}

从性能角度看:
typeid 趋向于便宜,简单查找存储在虚拟表中的指针。

From a performance point of view: typeid tends to be cheap, a simple lookup of a pointer stored in the virtual table. You can cheaply compare dynamic types for equality.

然后,一旦你知道你有正确的类型,你可以安全地使用 static_cast

Then, once you know you have the right type, you can safely use static_cast.

dynamic_cast 有一个名声是缓慢的(也就是说,函数调用,不像在比java中的转换慢),因为它也将分析类层次结构来处理继承(和多继承,也)。你不需要在这里处理。

dynamic_cast has a reputation for being slow (that is, slow as in "compared to virtual function calls", not slow as in "compared to a cast in java"), because it will also analyze the class hierarchy to deal with inheritance (and multiple inheritance, too). You don't need to deal with that here.

这篇关于比较C ++中的多态基本类型而不使用RTTI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆