c++ - 以 C++ 惯用方式实现多态运算符==()

标签 c++ macros virtual-functions

我认为我需要的就像一个纯虚函数,除了基类确实有一个派生类不能默认的实现(并且这个规则必须传播)。 final 的反面?

我有一些从公共(public)基础派生的类型。基类是有用的类型,一些派生类型是从其他派生类型派生的。我将只处理对基类的引用,但我需要一个 virtual operator==() 来查看它并调用适合每种情况的手动比较。 operator==() 的一种二维虚表。

实现不传播到派生类很重要,因为让这种情况意外发生可能会导致不兼容类型之间的比较落到基类实现中,在基类实现中它们兼容类型,这可能产生误报。

我的意思是让特定的功能等效案例比较相等,尽管它们在不同的类中表达。不过,我预计问题会扩展到其他操作,也许我对 operator==() 的使用在这里并不令人满意。

我并没有声称自己懂 C++——我只是一个试图成为地道的 C hack。

到目前为止,这是我已经解决的问题:

class base;
class foo;
class bar;
class baz;

#define COMPARE public: \
  virtual bool equal(base const &p) const; \
  virtual bool equal(foo const &p) const; \
  virtual bool equal(bar const &p) const; \
  virtual bool equal(baz const &p) const; \
  virtual bool operator==(base const &p) const { return p.equal(*this); }

class base {
  int a_;

 public:
  base(int a) : a_(a) {}

  COMPARE
};

class foo : public base {
  int b_;

 public:
  foo(int a, int b) : base(a), b_(b) {}

  COMPARE
};

class bar : public base {
  int c_;

 public:
  bar(int a, int c) : base(a), c_(c) {}

  COMPARE
};

class baz : public bar {
  int d_;

 public:
  baz(int a, int c, int d) : bar(a, c), d_(d) {}

  COMPARE
};

现在,感谢 COMPARE,所有 T::equal() 都必须实现,并且不允许它们中的任何一个退回到早期的实现。此外,每个类都有自己的 operator==(),它会为其自己的类型(而不是基类类型)调用适当的 equal()

我想要的是以 COMPARE 现在的方式执行这些规则,但不需要记住每个派生类都必须引用宏,理想情况下(C++ 惯用的)根本不使用宏。

执行此操作的正确 C++ 方法是什么?

最佳答案

我还在学习,但你所描述的听起来很像它可能需要双重调度和/或访问者模式。

对于双重分派(dispatch),类似于:

class base;
class foo;
class bar;
class baz;


class base {
    int a_;
public:
    base(int a) : a_(a) {}
    virtual bool operator==(const base&) const =0;
    virtual bool operator==(const foo&) const =0;
    virtual bool operator==(const bar&) const =0;
    virtual bool operator==(const baz&) const =0;
};

class foo : public base {
    int b_;
public:
    foo(int a,int b) : base(a),b_(b) {}
    bool operator==(const base&) const override;
    bool operator==(const foo&) const override;
    bool operator==(const bar&) const override;
    bool operator==(const baz&) const override;
};

class bar : public base {
    int c_;
public:
    bar(int a,int c) : base(a),c_(c) {}
    bool operator==(const base&) const override;
    bool operator==(const foo&) const override;
    bool operator==(const bar&) const override;
    bool operator==(const baz&) const override;
};

class baz : public bar {
    int d_;
public:
    baz(int a,int c,int d) : bar(a,c),d_(d) {}
    bool operator==(const base&) const override;
    bool operator==(const foo&) const override;
    bool operator==(const bar&) const override;
    bool operator==(const baz&) const override;
};

这看起来很像上面介绍的宏选项。 :)

在 TC++PL 第 4 版中,第 22.3.1 节谈到了双重分派(dispatch),其中提到了也许更愿意使用预先计算的查找表。有点像

bool equal(const base& b1,const base& b2)
    {
        auto i = index(type_id(b1),type_id(b2));
        return intersect_tbl[i](b1,b2);
    }

关于c++ - 以 C++ 惯用方式实现多态运算符==(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30810187/

相关文章:

c++ - SFINAE 关于模板成员重载

c++ - 宏观评估顺序

macros - 如何在 Razor 宏中获取当前成员

c++ - 提供虚函数错误

c++ - 我明白为什么了,但是 Virtual Functions/VTables 到底是如何允许通过指针访问正确的函数的呢?

c++ - STL maps中的key是如何升序排列的?

c++ - 从 lambda 内部调用函数返回

c++ - boost eval_if 的惰性评估

haskell - Emacs : Redefining command in Haskell-mode (haskell-mode-hook)

c++ - 在对象构造函数中将子结构值设置为纯虚函数返回的值是否安全?