具有返回值 (C++) 的函数
Functions with return values (C++)
当main((调用一个返回值为某种数据类型(原语或用户定义(的函数时,调用该函数的语句"通常"是一个赋值。
前任:-
class complex
{
private:
int real;
int imag;
public:
complex();
complex(int r,int i);
complex operator + (complex c);
};
假设,我的重载 "+" 的定义是这样的 -
complex complex::operator + (complex c)
{
this->real = this->real + c.real;
this->imag = this->imag + c.imag;
return *this;
}
我的主要功能如下 -
int main()
{
complex c1;
complex c2(5,4);
c1+c2;
}
在上面的 main(( 中,考虑语句 c1+c2 。编译器将其视为 c1.operator + (c2( 。当这个函数被 main 调用时,它会返回一个值给 main((。这个返回值会发生什么?
表达式 c1+c2
的值被代码忽略,因为您不会将其存储在任何地方。编译器最多会打印一些警告消息。要抑制此类警告消息,您可以编写:
(void)(c1+c2); //casting to void suppresses the warning messages!
看到这个:
- 为什么要将未使用的返回值强制转换为 void?
你的代码的真正问题..
但是,在代码中,operator+
的实现在语义上不正确。要理解这一点,请考虑这一点,
int a=10;
int b=5;
那么,您是否希望a+b
更改a
的值?a
应该成为15
吗?不。
如果你想要这个,那么你会写a+=b
。但是在你的代码中,c1+c2
的行为等同于c1+=c2
的语义,因为你在operator+
的实现中更新了this->real
和this->imag
的值,这在语义上是不正确的。
所以第一个修复是这样的:
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;
}
现在,这在语义上是正确的。
也就是说,仍然没有什么需要注意的。当你写c1+c2
时,你认为操作+
是否应用于任何一个对象?不。它不适用于其中任何一个,但成员函数operator+
c1
对象上调用,该对象成为函数内的指针this
。如果操作不适用于它,为什么要在c1
(或就此而言c2
(调用它?
此分析清楚地表明,operator+
不应该是类的成员函数。它应该是一个非成员函数,然后签名将是:
complex operator+(const complex &a, const complex &b);
但是有一个小问题:在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;
}
或者,您可以将最后两个语句连接为:
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'
}
但是还有另一种制作复制的方法。为什么要通过引用传递这两个参数?按值传递第一个参数将生成我们需要的副本。所以更好的实现是这样的:
complex operator+(complex a, const complex &b)
{ //^^^^^^^^^ pass-by-value
a += b; //a is a copy, after all - we can modify it!
return a;
}
希望有帮助。
它被分配到一个临时的(如果可以的话,不可见的(复数值中。此类值的生存期直到生成它的表达式结束,即 ;在 C1+C2 的末尾。因此,将创建一个新的时态对象来存储表达式的结果,并在该行的末尾销毁表达式。
你不应该修改你是 a + b 运算符中的"this",在计算 a + b 现在 a 保存表达式的结果。
return
值被丢弃;因为您没有将其存储在任何地方。
一个重要的建议:
理想情况下,operator +
的定义应该是这样的。
complex complex::operator + (const complex& c)
{ ^^^^^^^^^^^^^^
complex add;
add.real = this->real + c.real;
add.imag = this->imag + c.imag;
return add;
}
在您的原始代码中,制作了 2 个副本complex
;其中至少 1 个可以通过上述格式避免,其中参数通过 const 引用传递。
此外,在代码中,不应更改当前对象;(否则它会变成像operator +=()
(。因此,在函数内部创建一个临时函数并按值传递它。
在这种情况下,它被静默删除(但总和存储在c1
或c2
中(。编译器可能会(也可能不会(通过完全删除该行来优化代码,因为它不会做任何实质性的事情。得到的总和将由operator+
构造并返回(将创建一个临时变量(,然后立即销毁。
这在其他情况下也会发生。考虑一下:
c2 += c1;
您可以像这样将几个添加项链接在一起:
c4 += c3 += c2 += c1;
这是因为operator+=
也返回一个值,但就像在代码中一样,它会被忽略。
顺便说一句,我认为您想使用operator+=
.
只是被丢弃,但是当期望返回值的函数没有 return 语句时,AFAIK C++将显示错误。
另一种解决方案是在全局范围内使用 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;
}
// ...
};
使用此技术,您还可以通过添加以下内容来使用整数作为参数(在 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;
}
所以现在你也可以做
complex c1, c2, c3;
c3 = 1 + c2 + 8 + c1 + 2;
并且您的类缺少(虚拟(析构函数,我也会保护成员变量而不是私有:)
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么使用 "this" 指针调用派生成员函数?
- 将对象数组的引用传递给函数
- 函数调用中参数的顺序重要吗
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用不带参数的函数访问结构元素
- 代码在main()中运行,但在函数中出现错误
- 内置函数可查看CPP中的成员变量
- 如何获取std::result_of函数的返回类型
- 如何在c++中为模板函数实例创建快捷方式
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗