简体   繁体   English

具有返回值的函数(C ++)

[英]Functions with return values (C++)

When main() calls a function which has a return value of some datatype ( primitive or user-defined ) , the statement in which the function is called is 'usually' an assignment . 当main()调用一个返回值为某种数据类型(原语或用户定义)的函数时,调用该函数的语句“通常”是一个赋值。

Ex :- 例如: -

class complex
{

private:

    int real;
    int imag;

public:

    complex();
    complex(int r,int i);
    complex operator + (complex c);
};

Suppose , the definition of my overloaded " + " is like this - 假设,我的重载“+”的定义是这样的 -

complex complex::operator + (complex c)
{
    this->real = this->real + c.real;
    this->imag = this->imag + c.imag;
    return *this;
}

I have my main function as follows - 我的主要功能如下 -

int main()
{
    complex c1;
    complex c2(5,4);
    c1+c2;
}

In the main() above , consider the statement c1+c2 . 在上面的main()中,考虑语句c1 + c2 The compiler treats it as c1.operator + (c2) . 编译器将其视为c1.operator +(c2) When this function is called by main , it returns a value to main() . 当main调用此函数时,它会向main()返回一个值。 What happens to this return value ?? 这个返回值会发生什么变化?

The value of the expression c1+c2 is ignored by your code, as you are not storing it anywhere. 代码忽略表达式c1+c2的值,因为您没有将其存储在任何位置。 At most, the compiler will print some warning messages. 最多,编译器将打印一些警告消息。 To supress such warning messages, you could write : 要压制此类警告消息,您可以写:

(void)(c1+c2); //casting to void suppresses the warning messages!

See this: 看到这个:


The real issue with your code.. 你的代码真正的问题..

However, in your code, the implementation of operator+ is not semantically correct. 但是,在您的代码中, operator+的实现在语义上并不正确。 To understand that consider this, 要理解这一点,

 int a=10;
 int b=5;

then, do you expect a+b to change the value of a ? 那么,你希望a+b来改变的值a Should a become 15 ? 如果a变成15 No. 没有。

If you want that, then you would write a+=b instead. 如果你想要那个,那么你会写a+=b代替。 But in your code, c1+c2 behaves equivalent to the semantic of c1+=c2 , as you're updating the value of this->real and this->imag in your implementation of operator+ , which is not correct, semantically. 但是在你的代码中, c1+c2行为等同于c1+=c2的语义,因为你在operator+的实现中更新this->realthis->imag的值,这在语义上是不正确的。

So the first fix is this: 所以第一个修复是这样的:

complex complex::operator + (const complex& c) const
{                            
  complex result(c); //make a copy of c
  result.real += this->real; //add
  result.imag += this->imag; //add
  return result;
}

Now, this is semantically correct. 现在,这在语义上是正确的。

That said, there is still few things to be noted. 也就是说,仍有一些事情需要注意。 When you write c1+c2 , do you think the operation + is applied on either of the object? 当你编写c1+c2 ,你认为操作+是否应用于任何一个对象? No. It doesn't apply on any of them, yet the member function operator+ gets invoked on c1 object which becomes this pointer inside the function. 不。它不适用于它们中的任何一个,但是成员函数operator+c1对象上被调用, this对象在函数内部成为this指针。 Why should it be invoked on c1 (or for that matter c2 ) if the operation doesn't apply on it? 如果操作不适用于c1 (或c2 ),为什么要调用它?

This analysis makes it clear that operator+ shouldn't be a member function of the class. 该分析清楚地表明, operator+不应该是该类的成员函数。 It should be a non-member function instead, and the signature then would be: 它应该是非成员函数 ,然后签名将是:

complex operator+(const complex &a, const complex &b);

But there is a small problem: in the computation of a+b , it needs to access to the private members of the class ( real and imag are private members). 但是有一个小问题:在计算a+b ,它需要访问类(私有成员realimag是私有成员)。 So the solution is, operator+ should be implemented in terms of operator+= , and the latter should be added as a member function to the class, because the operation += in the expression a+=b does apply on a , as it modifies its value. 所以解决方案是, operator+应该用operator+= ,后者应该作为成员函数添加到类中, 因为表达式a+=b中的操作+=确实适用于a ,因为它修改了它的值。

So here is my implementation of both operators: 所以这是我对两个运算符的实现:

class complex
{
  //...
  public:

    //member function
    complex& operator+=(const complex & c)
    {
          real += c.real; //same as: this->real+=c.real; this is implicit
          imag += c.imag; //same as: this->imag+=c.real; this is implicit
          return *this;
    }
};

//non-member function (its non-friend as well)
complex operator+(const complex &a, const complex &b)
{
    complex result(a); //make copy of a by invoking the copy-constructor
    result += b;  //invokes operator+
    return result;
}

Or you could join last two statements as: 或者你可以加入最后两个声明:

complex operator+(const complex &a, const complex &b)
{
    complex result(a); //make copy of a by invoking the copy-constructor
    return result += b;  //invokes operator+, and then return updated 'result'
}

But there is another way to make copy. 但还有另一种制作副本的方法。 Why pass both arguments by reference? 为什么通过引用传递两个参数? Passing the first argument by value would make the copy we need. 按值传递第一个参数将使我们需要的副本。 So a better implementation would be this: 所以更好的实现是这样的:

complex operator+(complex a, const complex &b)
{               //^^^^^^^^^ pass-by-value
    a += b; //a is a copy, after all - we can modify it!
    return a;
}

Hope that helps. 希望有所帮助。

It gets assigned into a temporal (invisible if you may) complex value. 它被分配到一个时间(如果可能的话,不可见)复杂的值。 The lifetime of such value is until the expression that generated it ends, that's the ; 这种值的生命周期直到生成它的表达式结束,那就是; at the end of c1+c2. 在c1 + c2的末尾。 So a new temporal object is created to store the result of the expression, and its destructed at the end of that line. 因此,创建一个新的临时对象来存储表达式的结果,并在该行的末尾对其进行破坏。

You shouldn't be modifying 'this' in your a + b operator, after evaluating a + b now a holds the result of the expression. 您不应该在a + b运算符中修改'this',在评估a + b之后,现在a保存表达式的结果。

The return value is discarded; return值被丢弃; as you are not storing it anywhere. 因为你没有把它存放在任何地方。

One important advice : 一个重要的建议

Ideally the definition for operator + should look like. 理想情况下, operator +的定义应如下所示。

complex complex::operator + (const complex& c)
{                            ^^^^^^^^^^^^^^
  complex add; 
  add.real = this->real + c.real;
  add.imag = this->imag + c.imag;
  return add;
}

In your original code 2 copies of complex are made; 在您的原始代码中,制作了2份complex ; among which at least 1 can be avoided with above format where the argument is pass by const reference . 其中至少1可以通过上述格式避免,其中参数通过const引用

Also, in your code you should not change the current object; 此外,在您的代码中,您不应该更改当前对象; (otherwise it becomes like operator +=() ). (否则它变得像operator +=() )。 So create a temporary inside the function and pass it by value. 因此在函数内部创建一个临时函数并按值传递它。

In this case, it is silently dropped (but the sum is stored in c1 or c2 ). 在这种情况下,它会被静默删除(但总和存储在c1c2 )。 The compiler might (or might not) optimise the code by dropping the line entirely, because it doesn't do anything substantial. 编译器可能(或可能不)通过完全删除行来优化代码,因为它没有做任何实质性的事情。 The resulting sum will be constructed and returned by the operator+ , (a temporary variable will be created) and then destroyed immediately. 结果总和将由operator+构造和返回(将创建一个临时变量),然后立即销毁。

This happens in other cases, too. 在其他情况下也会发生这种情况。 Consider this: 考虑一下:

c2 += c1;

You can chain several additions like this together: 您可以将这样的几个附加链接在一起:

c4 += c3 += c2 += c1;

This is because operator+= also returns a value, but it is ignored like in your code. 这是因为operator+= 返回一个值,但是在代码中会被忽略。

By the way, I think you want to use operator+= . 顺便说一句,我认为你想使用operator+=

它被简单地丢弃,但是当期望返回值的函数没有return语句时,AFAIK C ++将显示错误。

Another solution is to use operator + in global scope but as a friend of your class: 另一种解决方案是在全局范围内使用operator + ,但作为您班级的朋友:

class complex
{
    // ...

public:

    // ...

    friend complex operator +(const complex &c1, const complex &c2)
    {
        complex c;
        c.real = c1.real + c2.real;
        c.imag = c1.imag + c2.imag;
        return c;
    }

    // ...

};

Using this technique you can also use an integer as argument (at the lhs) by adding: 使用此技术,您还可以使用整数作为参数(在lhs)添加:

    friend complex operator +(const int n, const complex &c)
    {
        complex c;
        c.real = n + c.real;
        c.imag = c.imag;
        return c;
    }

    friend complex operator +(const complex &c, const int n)
    {
        complex c;
        c.real = c.real + n;
        c.imag = c.imag;
        return c;
    }

So now you can also do 所以现在你也可以这样做

 complex c1, c2, c3;
 c3 = 1 + c2 + 8 + c1 + 2;

and your class is missing a (virtual) destructor, I would also make the member variables protected instead of private :) 并且你的类缺少(虚拟)析构函数,我也会使成员变量受保护而不是私有:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM