2
class student
{
 private:
     int age;
 public:
     student();
     student(int a) {age = a;}
     ~student() {};
     friend student& operator+ (int left, student& s);
     friend ostream& operator<< (ostream& o, student& s);
}

...

student& operator + (int left, student& s)
{
    s.age += left;
    return s;
}

ostream& operator<< (ostream& o, student& s)
{
    o << s.age << endl;
}


int main (void)
{ 
    student a (10);
    cout << 14 + a ;
    return 0;
}

所以我对上面的代码有两个问题。

  1. 为什么一定要return s;operator+ (int left, student& s)函数中做?为什么你不能把返回类型当作void你已经通过student引用传递对象?

  2. 似乎每当我放endlafter时都会出现错误14 + a,我发现了一个错误并且它没有打印出来。我知道这与 `operator <<' 有关,但我不知道它的确切原因,您如何防止这种情况发生?

4

3 回答 3

6

为什么你必须做 return s; 在 operator+ (int left, student& s) 函数中?

我必须说您的定义operator +很奇怪,因为它修改了右侧对象-而operator +通常不会,并按值返回一个新对象。

无论如何,operator +通常不会返回void,因此它允许链接,如:

14 + (16 + a)

但同样,operator +不应该修改右侧对象。您可能打算写类似operator +=. 考虑更改您的operator +.

似乎每当我在 14 + a 之后放置 endl 时都会出现错误,我发现一个错误并且它不会打印。我知道这与 `operator <<' 有关,但我不知道它的确切原因,您如何防止这种情况发生?

您的程序具有未定义的行为,因为您的重载operator <<不会返回任何内容。您应该添加一个返回语句:

ostream& operator<< (ostream& o, student const& s)
//                                       ^^^^^
{
    o << s.age << endl;
    return o;
//  ^^^^^^^^^ <== Without this, your program has undefined behavior.
//                Value-returning functions MUST return a value (with
//                the only exception of main())
}

此外,如上所述,您应该student通过引用来接受对象const,因为operator <<不会改变其状态(如果您不这样做,则不能operator <<const对象一起使用。

于 2013-05-16T08:04:15.147 回答
1

关于 1,您无需执行任何操作。该语言对使用重载运算符的操作没有任何限制。另一方面,可维护性和可读性确实要求重载运算符的行为方式类似于相应的内置运算符。因此:

  • 为名为 的类型重载加法是没有意义的 student,因为添加学生是没有意义的。(另一方面,你的类student看起来更像是一个抽象StudentAge。)

  • 加法(运算符+)不会修改它的任何一个参数。几乎没有例外。在您的情况下(假设 StudentAge,而不仅仅是Student),我可以看到三个运算符:StudentAge operator+( StudentAge const& lhs, int rhs ), StudentAge operator+( int lhs, StudentAge const& rhs ),最重要的是StudentAge& StudentAge::operator+=( int rhs ). 最后一个改变this,前两个可能应该根据第三个重载来实现。

  • 所有重载的加法运算符都应该返回一些东西,因为这是内置运算符所做的。 operator+返回一个新对象,并operator+=返回对this( return *this;) 的引用。再次,总是。

其他任何内容都是滥用,只会使读者感到困惑。

关于你的第二个问题:你已经声明 operator<<要返回一些东西,所以实现它来返回一些东西。只是落到最后是未定义的行为(即使没有其他任何内容)。

于 2013-05-16T08:22:57.187 回答
0

对于 1),请考虑以下代码:

student aStudent = anotherStudent + aDifferentStudent;

在这里,我们接受两个参数并返回一个值。这就是为什么您需要返回该类的实例。您当前的实现不是执行 operator+ 函数的标准方式,因为它修改了参数。考虑这里使用的字符串 operator+:

std::string aString = "Hello" + " " + "World";

从右到左操作,“”和“World”是文字字符串,传递给函数,该函数返回“World”,然后再次与“Hello”一起传递给函数(因为您有 2 次调用operator+ 方法)最终返回“Hello World”。您的实现不能这样做,因为 A)函数参数未声明为 const,并且 B)如果它们是,并且它进行了 const-cast 修改,您将尝试修改字符串文字 - 未定义的行为。

String 是一个很好的例子,说明了人们期望 operator+ 重载如何工作,以避免破坏最不意外的原则。

至于您的 << 和 endl 问题,原则上是相似的。您需要返回 o 实例。

于 2013-05-16T08:12:48.423 回答