复杂运算符*(double m,const 复杂的& C) {return c * m; }
*在上面的代码中,我试图将常数乘以复数。我收到一些错误,其中一个是[二元'运算符'有太多参数]
ostream&运算符<<(ostream& os, 复杂的& C) {os<< c.real<<“,”<< c.imaginary; return os;}
*****你能告诉我在这条线路上我做错了什么。 谢谢*****
#include <iostream>
using namespace std;
class Complex
{
private:
double real;
double imaginary;
public:
Complex();
Complex(double r, double i = 0);
Complex operator*(const Complex & c) const;
Complex operator*(double mult) const;
Complex operator*(double m, const Complex & c)
{ return c * m; }
ostream & operator<<(ostream & os, Complex & c)
{os << c.real <<"," << c.imaginary; return os;}
};
Complex::Complex()
{
real = imaginary = 0;
}
Complex::Complex(double r, double i )
{
real = r;
imaginary = i;
}
Complex Complex::operator*(const Complex & c) const
{
Complex mult;
mult.imaginary = imaginary * c.imaginary;
mult.real = real * c.real;
return mult;
}
Complex Complex::operator*(double mult) const
{
Complex result;
result.real = real * mult;
result.imaginary = imaginary * mult;
return result;
}
int main()
{
Complex B(5, 40);
Complex C(6, 15);
cout << "B, and C:\n";
cout << B << ": " << C << endl;
cout << "B * C: " << B*C << endl;
cout << "10 * B: " << 10*B << endl;
return 0;
}
答案 0 :(得分:3)
这两个运营商存在问题:
class Complex {
// ...
Complex operator*(double m, const Complex & c)
{return c * m;}
ostream & operator<<(ostream & os, Complex & c)
{os << c.real <<"," << c.imaginary; return os;}
// ...
};
在其他任何事情之前:operator<<
不应该改变复杂的输出,因此它应该是const
。 (否则您无法输出临时对象,因为它们不能绑定到非const引用。)
由于它们是非静态成员函数,因此它们具有隐式this
参数。有了它,它们有三个参数。但是,两者都是二元运算符。既然你不能让它们成为静态的(那只是因为规则这么说),你必须将它们作为自由函数来实现。但是,实施后,他们需要访问私人会员,所以你必须让他们成为你班级的朋友:
class Complex {
// ...
friend Complex operator*(double m, const Complex & c);
friend ostream & operator<<(ostream & os, const Complex & c);
// ...
};
Complex operator*(double m, const Complex & c)
{return c * m;}
ostream & operator<<(ostream & os, const Complex & c)
{os << c.real <<"," << c.imaginary; return os;}
在旁注中,可以在朋友声明中内联实现它们,这会使您几乎回到原始版本:
// note the friend
class Complex {
// ...
friend Complex operator*(double m, const Complex & c)
{return c * m;}
friend ostream & operator<<(ostream & os, const Complex & c)
{os << c.real <<"," << c.imaginary; return os;}
// ...
};
但是,如果您实现具体的数学类型,您的类型的用户将期望此类型的所有常见操作都可以使用它。也就是说,他们会期望c*=r
能够简单地运作。所以你也需要重载operator*=
。但是该运算符与operator*
几乎相同,因此最好在另一个运算符之上实现一个运算符。一个常见的习惯用法是将*=
(和+=
等)实现为成员函数(因为它们改变了左边的参数,对于它们访问其私有数据是个好主意)和{{1作为非成员而已。 (通常这比其他方式更有效率。):
operator*
IMO是最好的解决方案。
实现乘法的方式效率低下:
// note the friend
class Complex {
// ...
Complex& operator*=(double rhs)
{return /* whatever */;}
friend ostream & operator<<(ostream & os, const Complex & c)
{os << c.real <<"," << c.imaginary; return os;}
// ...
};
inline Complex operator*(Complex lhs, double rhs) // note: lhs passed per copy
{return lhs*=rhs;}
inline Complex operator*(double lhs, const Complex& rhs)
{return rhs*lhs;}
当你说 Complex Complex::operator*(const Complex & c) const
{
Complex mult;
mult.imaginary = imaginary * c.imaginary;
mult.real = real * c.real;
return mult;
}
时,你会调用你的类的默认构造函数,它将实部和虚部初始化为Complex mult;
。接下来你要做的就是覆盖那个值。为什么不一步到位:
0
甚至更简洁
Complex Complex::operator*(const Complex & c) const
{
Complex mult(real * c.real, imaginary * c.imaginary);
return mult;
}
当然,每次乘法只需两次。但是 - 你不希望在你的图形驱动程序的某个内循环中有这个。
此外,您的构造函数未实现The Way It Ought To be(TM)。要初始化成员数据,您应该使用初始化列表:
Complex Complex::operator*(const Complex & c) const
{
return Complex(real * c.real, imaginary * c.imaginary);
}
虽然它对Complex::Complex()
: real(), imaginary()
{
}
Complex::Complex(double r, double i)
: real(r), imaginary(i)
{
}
这样的内置类型没有任何影响,但它也没有任何影响,并且不养成习惯是好的。使用用户定义的类型(一个有点不幸的名称,因为它适用于所有非内置函数,甚至像double
这样的类型,它没有被用户定义)具有非平凡的默认构造函数,它确实有所作为:效率低得多。
原因是,当执行通过初始std::string
时,C ++保证您的数据成员对象可以访问和使用。为此,必须构建它们,因为构造是将原始内存转换为对象的原因。因此,即使您没有显式调用构造函数,运行时系统仍将调用默认构造函数。如果您接下来要做的是覆盖默认构造的值,那么您再次浪费CPU周期。
最后,此构造函数{
充当隐式转换运算符。也就是说,例如,如果您打算调用Complex(double r, double i = 0)
,但忘记包含它,但是范围内有f(real)
,则编译器会行使其执行一次用户定义转换的权利, call f(const complex&)
变为f(4.2)
,并且默认调用错误的函数。这非常危险。
为了避免这种情况,你应该标记所有只能用一个参数调用的构造函数f(Complex(4.2))
:
explicit
答案 1 :(得分:2)
不要将Complex operator*(double m, const Complex & c)
和ostream声明为成员函数(也称为方法):将它们声明为朋友函数! (如果你甚至需要他们成为朋友,如果你有明显的虚拟和真实部分的内联访问方法,你就不会这样做 - 但无论如何,重点是他们必须在之外类!)。
答案 2 :(得分:0)
对于成员函数,operator*
和operator<<
只接受一个参数,因为Complex
对象已经隐含给出,即
c * r
转换为
c.operator*(r)
如果您希望使用两个参数形式,那么您正在寻找外部朋友功能。虽然Alex指出,如果您设置了re
和im
个访问者,那么您的外部运营商就不必是朋友。