C++ 运算符重载'+';C+中的运算符+;

C++ 运算符重载'+';C+中的运算符+;,c++,operator-overloading,C++,Operator Overloading,下面的代码在VisualStudio2008上运行,我遇到了一个问题。当您有一个要重载的语句时,如何为操作符+编写函数定义,如下所示 class Distance { private: int feet,inches; }; main...... Distance Obj, Obj1(2, 2); Obj = 3 + Obj1; // This line here Obj1+3很容易,但是这个编译器如何知道它必须进行重载呢 假设我必须将值3添加到Obj1的数据成员

下面的代码在VisualStudio2008上运行,我遇到了一个问题。当您有一个要重载的语句时,如何为
操作符+
编写函数定义,如下所示

class Distance
{
    private:
        int feet,inches;
};

main......

Distance Obj, Obj1(2, 2);

Obj = 3 + Obj1; // This line here
Obj1+3
很容易,但是这个编译器如何知道它必须进行重载呢


假设我必须将值3添加到
Obj1

的数据成员
feet
,您需要编写一个自由函数(在
之外):

如果
..
需要使用
Distance
的私人成员,那么请在
Distance
中与之成为朋友

class Distance
{
  ...
  friend Distance operator+(int lhs, const Distance& rhs);
};
最后,如果您希望能够使用左侧的
+
距离
,只需定义另一个
操作符+
重载,如上所述,但第一个参数是
距离


所有这些都表明,我将避免做你看起来在做的事情。作为
Distance
类的用户,我不知道您所做的是增加3英尺、3英寸还是3米。如果您不打算使用国际单位制(米),则不应允许使用非距离值进行加法。

通常,这种形式的运算符将声明为:

Distance operator+(int lhs, const Distance& rhs) {
  // Assuming the int value represents feet
  return Distance(rhs.feet + lhs, rhs.inches);
}
您可能还需要定义对称:

Distance operator+(const Distance& lhs, int rhs) {
  // Assuming the int value represents feet
  return Distance(lhs.feet + rhs, lhs.inches);
}

另外,我建议你听从James McNellis的建议——如果你只有一个成员在一个单位中表示长度,你的工作就会简化。

现在有几个答案建议使用非成员的
操作符+
重载来允许“添加”
距离
int
对象。这真的没有意义:将一个有单位的
距离添加到一个没有单位的
int
,意味着什么

但是,将两个
距离
对象添加在一起是有意义的。如果你有一个两英尺的距离,再加上另一个三英尺的距离,你就得到了五英尺的距离。这是有道理的

您可以通过在两个
距离
对象之间重载
操作符+
来实现这一点(为简单起见,我假设您的
距离
只有一个包含英寸的字段。在实际应用程序中,您不希望英寸和英尺有单独的字段。您可能希望使用SI单位,如米,但这取决于应用程序,完全取决于您):

但是,如果你想按照自己的想法做一些事情,这对你没有帮助

Distance d;
d = d + 42; // assume 42 has the same units as a Distance object has
为了使其有意义,您可以使用转换构造函数:

struct Distance
{
    Distance(int in = 0) : inches(in) { }
private:
    int inches;
};
这里的构造函数是一个转换构造函数,因为它不是显式的,可以用单个参数调用。它允许将单个的
int
(或隐式转换为
int
的值)转换为
距离
对象。这允许您编写

Distance d;
d = d + 42;

为什么这与使用带
距离
int
参数的
运算符+
重载不同?很简单:它强制在加法之前进行从
int
距离的转换,因此实际加法不必关心其操作数:它只需添加两个距离s并让
距离
构造函数处理需要进行的任何转换。

除了重载
++
运算符以两个
距离
对象外,还应避免重载
运算符+(const Distance&,int)
正如其他答案中所指出的。最好定义一些常量,如:

const Distance feet(1,0);
const Distance inch(0,1);
还可以重载
运算符*(int,const Distance&)
,这样您就可以编写:

Distance dist = 3 * feet + 5 * inch;
Distance dist2 = dist + 2 * feet;

更具可读性。

最好用一个长度单位来测量距离(例如,英寸,或者最好用一些国际单位制,如米(好的,好的,国际单位制并不总是可取的,但通常是))。很可能彻底解决了原来的问题。@James McNellis:如果出于任何原因,此构造函数需要显式,这会发生什么变化?这是否表明存在设计缺陷?@chubsdad:嗯,如果该构造函数是显式的,那么它就不是一个转换构造函数(根据定义,转换构造函数是一个非显式且可以用单个参数调用的构造函数)。如果该构造函数是显式的,则不会将其视为用户定义的转换,并且您将无法执行
d+42
。您需要执行
d+Distance(42)
。在某些情况下,转换构造函数是有用的,这可能是其中之一。我认为转换构造函数的存在不会立即表明存在设计缺陷。即使排除
3+距离(4)
,也需要对
3*距离(4)进行类似的重载
@MSalters:如果我正确理解了你的评论,你是说如果你需要其他操作符(比如
操作符*
),我的转换构造函数建议就会失败。我完全同意(我会在早上重新讨论这个答案,除非有人抢先回答我;反正我不知道凌晨3点回答问题在做什么…;-)@James McNellis:是的,
操作符*(距离,距离)
将返回一个
区域
。因此需要
距离操作符*(int,Distance)
;隐式转换int->Distance不行。即使您使用的是国际单位制,为了与乘法保持一致,通常也不允许弱类型加法。
距离(3)*距离(4)
距离(3)*4
两者都有意义,但有不同的含义。你不能承担从int到Distance的隐式转换。嗯?如果
Distance
以米为单位,那么它们的计算结果肯定都是
距离(12)
?错误C2511:'Distance Distance Distance::operator+(int,const Distance&'),它表示重载的成员函数
const Distance feet(1,0);
const Distance inch(0,1);
Distance dist = 3 * feet + 5 * inch;
Distance dist2 = dist + 2 * feet;