【问题标题】:Why does my operator overloading handle left versus right objects?为什么我的运算符重载处理左右对象?
【发布时间】:2014-03-05 21:14:37
【问题描述】:

我有一个关于运算符重载的问题。下面是我的示例代码。如果你能通读它,我的问题就在下面。

//class definition
class example
{
private:
    int a ; // Defined in FeetInches.cpp
public:
    void seta(int f)
    {
        a = f;
    }
    example operator + (const example &); // Overloaded +

    int geta()
    {
        return a;
    }
};

example example::operator + (const example &right)
{
    example temp;

    temp.a = a + right.a;
    return temp;
}

//主要

#include "header" //this is the class definition above
#include <iostream>
using namespace std;

int main()
{
    example r;
    r.seta(1);

    example s;
    s.seta(1);

    example t;
    t = r + s;
    t = r + 1;  //if included it won't compile
    t = 1 + r; //if included it won't compile

    int x = t.geta();
    cout << x;

    cin.get();
    return 0;
}

我了解当您尝试使用运算符重载将对象一起添加时,它们应该是相同的。

这是一个问题: 我最近看到该对象何时位于它编译的运算符的一侧,但当它位于另一侧时却没有。如:

t = r + 1; 它已编译。 t = 1 + r; 没有。

(我也知道在我的示例中这两种方式都不起作用,但更容易用代码来构建问题。)

当对象在运算符的一侧时,运算符重载如何编译,但在另一侧时不编译。

谢谢

【问题讨论】:

  • 尝试使用operator+: r.operator+(1) 重写您的作业。换一种方式试试,你会从编译器的角度看到。
  • 这就是为什么他们经常建议将operator+=实现为成员函数,然后将operator+实现为全局函数。这样,隐式转换可以发生在 + 运算符的左侧或右侧。

标签: c++ operator-overloading


【解决方案1】:

如果你详细地重写有问题的语句,它看起来像:

t.operator=(1.operator+(r));

这没有多大意义并且会使编译器感到困惑。

被混淆了,它既可以将数字 1 转换为 example 的实例,也可以将变量 r 转换为整数。不幸的是,你也没有在课堂上提供足够的信息来做这件事。

如果你为你的类提供一个接受整数的构造函数,事情可能会变得不那么混乱:

class example
{
  public:
    example(int new_value) : a(new_value)
      { ; }
};

现在您已经为编译器提供了将整数转换为examples 的方法。

另一种选择是提供转换或转换运算符:

class example
{
  public:
    int operator int (const example& e)
    {
      return e.a;
    }
};

还有其他替代方法,例如创建一个采用整数的加法方法。

编辑 1:
如果您正在设计 units 类,请注意常量。您不知道常数的单位是什么,例如英尺或英寸。编译器将无法提供帮助,因为数值常量没有与之关联的单位。

【讨论】:

  • 编译器将t = 1 + r; 视为t.operator=(operator+(1, r));,因为1 不是可以定义自己的operator+() 方法的对象类型。您正在关注对象一元运算符,但不要忘记也存在全局二元运算符。
【解决方案2】:

其实很简单,当你重载操作符时,你可以通过两种方式来实现:

首先就像你做的那样。您在其中为您的类插入了重载运算符。这样左参数必须是这个类的对象。为什么?因为当您调用此运算符时,您可以调用类中的每个函数。你不能这样做,因为你不能用其他类型调用这个函数。

其次,您将重载运算符作为班级的朋友。 在你的课堂上,你写了这行:

 friend example& operator + (const example &left, const example &right);

在你的类定义之后你把这个:

example& operator + (const example &left, const example &right){...}

所以如果你想添加整数或其他类型,你必须修改你的操作符来添加它:

example& operator + (const example &left, const int right){...}

或者这个:

example& operator + (const int left, const example &right){...}

如果要从运算符的左侧或右侧添加 int,请选择一个或两个。

【讨论】:

    【解决方案3】:

    t = r + 1; 表示t = r.operator+(1); 如果r 定义了匹配的operator+() 方法,否则表示t = operator+(r, 1);。它无法编译,因为您没有定义任何 + 运算符,该运算符在左侧采用 example,在右侧采用 int,例如:

    // as a class method:
    
    class example
    {
        ...
    public:
        ...
        example operator + (int right) const;
    };
    
    example example::operator + (int right) const
    {
        example temp;
        temp.seta(a + right);
        return temp;
    }
    

    或者:

    // as a global operator:
    
    class example
    {
        ...
    public:
        ...
        friend example operator + (const example& left, int right);
    };
    
    example operator + (const example& left, int right)
    {
        example temp;
        temp.seta(left.a + right);
        return temp;
    }
    

    如果您定义了一个将int 作为输入的构造函数,那么当您将int 值传递给example::operator+(const example&amp;) 方法时,编译器可能会创建一个临时example,例如:

    class example
    {
        ...
    public:
        example (int f);
        ...
        example operator + (const example& right);
    };
    
    example::example::(int f)
        : a(f)
    {
    }
    
    example example::operator + (const example& right)
    {
        example temp;
        temp.a = a + right.a;
        return temp;
    }
    

    同样,t = 1 + r; 表示t = operator+(1, r);(因为 1 不是类类型)。它无法编译,因为您没有定义一个全局 + 运算符,该运算符在左侧采用 int,在右侧采用 example

    class example
    {
        ...
    public:
        ...
        friend example operator + (int left, const example& right);
    };
    
    example operator + (int left, const example& right)
    {
        example temp;
        temp.a = left + right.a;
        return temp;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-16
      • 2010-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多