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

jsp*_*p99 3 c++ function

当main()调用一个返回值为某种数据类型(原始或用户定义)的函数时,调用该函数的语句"通常"是一个赋值.

例如: -

class complex
{

private:

    int real;
    int imag;

public:

    complex();
    complex(int r,int i);
    complex operator + (complex c);
};
Run Code Online (Sandbox Code Playgroud)

假设,我的重载"+"的定义是这样的 -

complex complex::operator + (complex c)
{
    this->real = this->real + c.real;
    this->imag = this->imag + c.imag;
    return *this;
}
Run Code Online (Sandbox Code Playgroud)

我的主要功能如下 -

int main()
{
    complex c1;
    complex c2(5,4);
    c1+c2;
}
Run Code Online (Sandbox Code Playgroud)

在上面的main()中,考虑语句c1 + c2.编译器将其视为c1.operator +(c2).当main调用此函数时,它会向main()返回一个值.这个返回值会发生什么变化?

Naw*_*waz 8

表达式的值c1+c2会被代码忽略,因为您不会将其存储在任何位置.最多,编译器将打印一些警告消息.要压制此类警告消息,您可以写:

(void)(c1+c2); //casting to void suppresses the warning messages!
Run Code Online (Sandbox Code Playgroud)

看到这个:


你的代码真正的问题..

但是,在您的代码中,实现在operator+语义上并不正确.要理解这一点,

 int a=10;
 int b=5;
Run Code Online (Sandbox Code Playgroud)

那么,你期望a+b改变它的价值a吗?应该a成为15?没有.

如果你想要,那么你会写a+=b.但是,在你的代码,c1+c2行为等同于语义的c1+=c2,因为你要更新的价值this->real,并this->imag在你的实现operator+,这是不正确的,语义.

所以第一个修复是这样的:

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;
}
Run Code Online (Sandbox Code Playgroud)

现在,这在语义上是正确的.

也就是说,仍有一些事情需要注意.在你写的时候c1+c2,你认为这个操作+适用于任何一个对象吗?不.它不适用于它们中的任何一个,但成员函数operator+c1对象上被调用,该对象成为this函数内的指针.如果操作不适用于它,为什么要调用c1(或者就此而言c2)呢?

这种分析清楚地表明,operator+不应该是该类的成员函数.它应该是非成员函数,然后签名将是:

complex operator+(const complex &a, const complex &b);
Run Code Online (Sandbox Code Playgroud)

但是存在一个小问题:在计算中a+b,它需要访问类的私有成员(real并且imag是私有成员).所以解决方案operator+应该是实现的operator+=,后者应该作为成员函数添加到类中,因为+=表达式a+=b中的操作确实适用于a它,因为它修改了它的值.

所以这是我对两个运算符的实现:

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;
}
Run Code Online (Sandbox Code Playgroud)

或者你可以加入最后两个声明:

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'
}
Run Code Online (Sandbox Code Playgroud)

但还有另一种制作副本的方法.为什么通过引用传递两个参数?按值传递第一个参数将使我们需要的副本.所以更好的实现是这样的:

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

希望有所帮助.