在没有RTTI的情况下比较C++中的多态基类型

ogg*_*ter 7 c++ polymorphism

我有一些基本类型的Shape指针.我想使用==运算符比较这些对象.如果对象具有不同的派生类型,则==运算符显然应返回false.如果它们具有相同的派生类型,则应该比较派生类型的成员.

我已经读过,使用C++ RTTI是不好的做法,只能在罕见和必要的情况下使用.据我所知,如果不使用RTTI,通常无法解决这个问题.每个重载的==运算符都必须检查typeid,如果它们相同,则执行dynamic_cast并比较成员.这似乎是一种常见的需求.这个问题有某种成语吗?

#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 ==
}
Run Code Online (Sandbox Code Playgroud)

wol*_*ang 10

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

从设计的角度来看,我认为这正是RTTI的用途,任何替代解决方案必然会更加丑陋.

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

从性能的角度来看: typeid往往是便宜的,简单地查找存储在虚拟表中的指针.您可以廉价地比较动态类型的相等性.

然后,一旦您知道自己拥有合适的类型,就可以放心使用static_cast.

dynamic_cast因为"与虚拟函数调用相比"而言速度慢(就像"与java中的强制转换相比"一样慢),因为它还会分析类层次结构来处理继承(和多个继承,也).你不需要在这里处理.

  • 这不仅仅是你"不需要"在这里使用dynamic_cast,你不能**.否则,如果MagicCircle继承自Circle,那么你会得到`circle == magic_circle`和`magic_circle!= circle`的情况. (4认同)