c++ - 为类层次结构重载 operator== 的正确方法是什么?

标签 c++ operator-overloading

假设我有以下类层次结构:

class A
{
    int foo;
    virtual ~A() = 0;
};

A::~A() {}

class B : public A
{
    int bar;
};

class C : public A
{
    int baz;
};

为这些类重载 operator== 的正确方法是什么?如果我将它们全部设为自由函数,那么 B 和 C 不能在不强制转换的情况下利用 A 的版本。它还会阻止某人仅引用 A 进行深度比较。如果我将它们设为虚拟成员函数,那么派生版本可能如下所示:

bool B::operator==(const A& rhs) const
{
    const B* ptr = dynamic_cast<const B*>(&rhs);        
    if (ptr != 0) {
        return (bar == ptr->bar) && (A::operator==(*this, rhs));
    }
    else {
        return false;
    }
}

再一次,我仍然需要施法(感觉不对)。有没有首选的方法来做到这一点?

更新:

目前只有两个答案,但看起来正确的方法类似于赋值运算符:

  • 将非叶类抽象化
  • 在非叶类中 protected 非虚拟
  • 叶类中的公共(public)非虚拟

任何用户尝试比较两个不同类型的对象都不会编译,因为基函数受到保护,叶类可以利用父类的版本来比较这部分数据。

最佳答案

对于这种层次结构,我肯定会遵循 Scott Meyer 的 Effective C++ 建议并避免使用任何具体的基类。无论如何,您似乎都在这样做。

我会将 operator== 实现为自由函数,可能是 friend ,仅用于具体的叶节点类类型。

如果基类必须有数据成员,那么我会在派生类的 operator== 可以使用。

例如

bool operator==(const B& lhs, const B& rhs)
{
    return lhs.isEqual( rhs ) && lhs.bar == rhs.bar;
}

通过避免使用适用于抽象基类的 operator== 并保护比较函数,您永远不会意外地在客户端代码中遇到只有两个不同类型对象的基础部分的回退进行比较。

我不确定我是否会使用 dynamic_cast 实现虚拟比较函数,我不太愿意这样做,但如果确实需要它,我可能会选择基类(not operator==)中的纯虚函数,然后在具体派生类中使用 operator== 用于派生类。

bool B::pubIsEqual( const A& rhs ) const
{
    const B* b = dynamic_cast< const B* >( &rhs );
    return b != NULL && *this == *b;
}

关于c++ - 为类层次结构重载 operator== 的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1691007/

相关文章:

c++ - 使用指针 vector 循环其他 vector

c++ - 错误 : 'operator[]' is not defined

c++ - 为什么 .* 运算符不能在 C++ 中重载?

c# - 重载显式 CAST 运算符

c++ - 与 Sunstudio 的静态链接

c++ - c++ 删除内存

c++ - 获取 ostream 的插入运算符

Python重载变量赋值

c++ - 无法使用 GetProcAddress() 从 DLL 加载某些函数

c++ - 更高效的稀疏矩阵元素访问器