8

假设我有一个类型层次结构:

struct B { ... };

struct D1 : B { ... };
struct D2 : B { ... };
...
struct Dn : B { ... };

每个 Di 都有自己的operator==定义:

struct Di : B
{
    bool operator==(const Di&) const { ... }
    ...
};

我现在想定义 Boperator==使得:

struct B
{
    bool operator==(const B& that) const
    {
        // psuedo-code
        let i, such the dynamic type of this is Di
        let j, such the dynamic type of that is Dj

        if (i != j)
            return false;
        else
            return Di::operator==(this, that);
    }
 }

组织这个或写这个的最佳方式是什么?

(最终目标是我想使用具有 B* 值类型的标准容器类型(例如std::set<B*>),但是Di::operator==s当它们来自同一个派生类时使用自定义)

4

2 回答 2

6

在基类中定义一个受保护的虚函数。使其成为纯虚拟,以确保每个子类都Di提供一个实现。该函数将知道转换的目标,因为它属于 a Di。从基类中的运算符调用该函数==,并让它执行比较,如下所示:

struct B {
    bool operator==(const B& that) const {
        return this->equals(that);
    }
protected:
    virtual bool equals(const B& other) const=0;
};
struct D1 {
protected:
    virtual bool equals(const B& other) const {
        D1 *that = dynamic_cast<D1*>(&other);
        if (!that) return false;
        // Perform D1-specific comparison here.
        // You can use the == operator of D1, but you do not have to:
        return (*this) == (*that);
    }
};

这种构造的效果是使==操作符的实现成为虚拟的。

于 2013-05-28T12:45:07.227 回答
1

这是dasblinkenlight 解决方案的轻微变化,具有附加功能(例如,更少的代码重复)

#include <typeinfo> // for typeid

struct B {

  bool operator==(const B& that) const {

    if (this == &that) // trivially equal
      return true;

    if (typeid(*this) != typeid(that)) // trivially different
      return false;

    return equals(that); // delegates to the virtual function
  }

  // polymorphic classes must have virtual destructors
  virtual ~B() = default;

protected:

  virtual bool equals(const B& that) const = 0;

};

struct D1 : B {

  bool operator ==(const D1& that) const {
    // ...
  }

private:

  // private because this function is not meant to be called except through
  // B::equals
  bool equals(const B& that) const override {
    // static_cast is safe here because execution only gets here if the
    // dynamic type of that is D1 (this was tested in B::operator =()
    return *this == static_cast<const D1&>(that);
  }

};
于 2013-05-28T16:04:31.340 回答