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

标签 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 ==
}

最佳答案

使用 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;
}

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

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

dynamic_cast 以速度慢着称(也就是说,“与虚函数调用相比”慢,而不是“与 java 中的转换相比”),因为它也会分析类层次结构以处理继承(以及多重继承)。你不需要在这里处理。

关于c++ - 在没有 RTTI 的情况下比较 C++ 中的多态基类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11332075/

相关文章:

scala - scala中高阶多态性的常见做法

c++ std::vector 迭代器构造函数 first == last

c++ - 为什么语句是: "undefined behavior means the compiler can do anything it wants" true?

c++ - 在 OpenCL clCreateContext 中从 void (*) (...) 到 void (*) (...) 的无效转换

java - 如何通过 Java 中泛型的特定派生来专门化对泛型函数的调用?

C# 将泛型类型向上转型为接口(interface)

c++ - 为什么堆栈溢出在 Visual C++ 中没有抛出错误?

c++ - 尝试使用 main 运行类时出错

c++ - 模板多态性和unique_ptr

polymorphism - 修复语言环境扩展中的类型变量