我可以让 operator== 虚拟来实现平等吗? [英] Can I make operator== virtual to implement equality?

查看:54
本文介绍了我可以让 operator== 虚拟来实现平等吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从这个使用继承时实现 operator== 问题,我看到人们说operator== 不应该是 virtual(接受的答案甚至说operators cannot be virtual",我发现这不是稍后为真):

<块引用>

c++ 允许运算符是虚拟的.但我不会让它们成为虚拟的.多态性和运算符实际上并不能很好地结合在一起(并且自由运算符函数显然根本不能是虚拟的).---- 约翰内斯·绍布 - litb

<块引用>

-1.使 Person::operator== 虚拟化是不够的:必须重写 Employee::operator== 以具有相同的签名.此外,这仍然会导致道格拉斯指出的问题,即比较操作的不对称性,这是......很奇怪.---- 吕克·图拉耶

我不明白为什么我不能制作 operator== virtual.我写了这段代码,似乎可以很好地处理多态:

#include #include <类型信息>使用命名空间标准;结构基{int b1 = 1;int b2 = 2;virtual bool operator==(const Base& rhs) const {cout<<基地"<<结束;if (typeid(*this) != typeid(rhs)) {cout<<假"<<结束;返回假;}别的 {cout<<真实"<<结束;返回 (b1 == rhs.b1) &&(b2 == rhs.b2);}}};结构派生:公共基础{int d1 = 3;int d2 = 4;virtual bool operator==(const Base& rhs) const override {cout<<衍生"<<结束;if (typeid(*this) != typeid(rhs)) {cout<<假"<<结束;返回假;}别的 {cout<<真实"<<结束;const Derived&rrhs = static_cast<const Derived&>(rhs);返回 (b1 == rrhs.b1) &&(b2 == rrhs.b2) &&(d1 == rhs.d1)&&(d2 == rhs.d2);}}};int main(){派生 d;基数 b1、b2;基*bptr1、*bptr2、*bptr3;bptr1 = &b1;bptr2 = &d;bptr3 = &b2;如果 (*bptr2 == *bptr1) {cout<<1"<<结束;}别的 {cout<<0"<<结束;}如果 (*bptr3 == *bptr1) {cout<<1"<<结束;}别的 {cout<<0"<<结束;}如果 ((d == b1) != (b1 == d)) {cout<<xxx";}返回0;}

我的代码有问题吗?

解决方案

无法定义适用于多态类层次结构的通用比较运算符.这里有几个例子.

示例一.我们正在制作一个算术层次结构.对 BigNumber 进行操作,底层框架将选择正确的表示.

class BigNumber { ... };类 BigInteger : 公众号 { ... };类 BigRational : 公众号 { ... };类 BigFloating : 公众号 { ... };

如果我们认同不同动态类型的两个对象永远不相等的哲学,那么 BigInteger(0) 不等于 BigRational(0,1)BigFloating(0.0).这打破了我们所知的算术.

示例二.我们正在制作几何层次结构.

class Shape { ... };类三角形:公共形状{ ... };类矩形:公共形状{ ... };

到目前为止一切顺利.Triangle 永远不等于 Rectangle ,对吧?让我们添加颜色.

class ColouredTriangle : public Triangle { ... };

糟糕!现在我们的小 CAD 程序已经停止工作,因为我们已经用 ColouredTriangle 替换了 Triangle 之一,即使几何引擎不知道颜色并且只对颜色感兴趣几何特性.更糟糕的是,即使我们将所有 Triangle 替换为 ColouredTriangle,并且如果我们希望几何引擎完全像以前一样工作,所有颜色都需要相同.

也许在某些应用领域中,首先比较类型 ID 是一种用于对象比较的合理方法,但我还没有看到.

无论您使用何种编程语言,这都适用.

From this implementing operator== when using inheritance question, I see people say that operator== should not be made virtual (the accepted answer even says "operators cannot be virtual", which I found that is not true later):

c++ allows operators to be virtual. but i wouldn't make them virtual. polymorphism and operators actually don't fit together very well (and free operator functions obviously can't be virtual at all). ---- Johannes Schaub - litb

-1. Making Person::operator== virtual is not sufficient: Employee::operator== must be rewritten to have the same signature. Moreover, this would still lead to the issue pointed by Douglas, i.e. assymetry of the comparison operation, which is...weird. ---- Luc Touraille

I don't understand why I can't make operator== virtual. I wrote this code and seem to work well with polymorphism:

#include <iostream>
#include <typeinfo>
using namespace std;

struct Base {
    int b1 = 1;
    int b2 = 2;
    virtual bool operator==(const Base& rhs) const {
        cout << "Base" << endl;
        if (typeid(*this) != typeid(rhs)) {
            cout << "false" << endl;
            return false;
        }
        else {
            cout << "true" << endl;
            return (b1 == rhs.b1) && (b2 == rhs.b2);
        }
    }
};

struct Derived : public Base {
    int d1 = 3;
    int d2 = 4;
    virtual bool operator==(const Base& rhs) const override {
        cout << "Derived" << endl;
        if (typeid(*this) != typeid(rhs)) {
            cout << "false" << endl;
            return false;
        }
        else {
            cout << "true" << endl;
            const Derived& rrhs = static_cast<const Derived&>(rhs);
            return (b1 == rrhs.b1) && (b2 == rrhs.b2) && (d1 == rrhs.d1)
                && (d2 == rrhs.d2);
        }
    }
};

int main()
{
    Derived d;
    Base b1, b2;
    Base *bptr1, *bptr2, *bptr3;
    bptr1 = &b1;
    bptr2 = &d;
    bptr3 = &b2;
    
    if (*bptr2 == *bptr1) {
        cout << "1" << endl;
    }
    else {
        cout << "0" << endl;
    }

    if (*bptr3 == *bptr1) {
        cout << "1" << endl;
    }
    else {
        cout << "0" << endl;
    }

    if ((d == b1) != (b1 == d)) {
        cout << "xxx";
    }
    return 0;
}

Is there any problem with my code?

解决方案

There is no way to define a generic comparison operator that would work in polymorphic class hierarchies. Here are a couple of examples.

Example one. We are making an arithmetic hierarchy. Operate on BigNumber and the underlying framework will choose the right representation.

class BigNumber { ... };
class BigInteger : public Number { ... };
class BigRational : public Number { ... };
class BigFloating : public Number { ... };

If we subscribe to the philosophy that two objects of different dynamic types are never equal, then BigInteger(0) is not equal to BigRational(0,1) or BigFloating(0.0). This breaks arithmetics as we know it.

Example two. We are making a geometry hierarchy.

class Shape { ... };
class Triangle : public Shape { ... };
class Rectangle : public Shape { ... };

So far so good. A Triangle is never equal to a Rectangle, right? Let's add colour.

class ColouredTriangle : public Triangle { ... };

Oops! Now our little CAD program has stopped working because we have replaced one of the Triangles with a ColouredTriangle, even though the geometry engine has no idea about colour and is only interested in geometric properties. Worse still, even if we replace all Triangles with ColouredTriangles, and if we want the geometry engine to work exactly as before, all the colours need to be the same.

Perhaps there are application domains where comparing type-IDs first is a sound approach to object comparison, but I have yet to see one.

This applies regardless of your programming language.

这篇关于我可以让 operator== 虚拟来实现平等吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆