gpt4 book ai didi

c++ - 将一个常数乘以一个复数 & 运算符重载问题

转载 作者:行者123 更新时间:2023-11-27 22:31:40 26 4
gpt4 key购买 nike

Complex operator*(double m, const Complex & c) { return c * m; }

*在上面的代码中,我试图将一个常数乘以一个复数。我收到一些错误,其中之一是 [二进制“运算符 ”的参数太多]

ostream & operator<<(ostream & os, Complex & 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;
}

最佳答案

这两个操作符有问题:

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 . (否则你不能输出临时对象,因为它们不能绑定(bind)到非常量引用。)

因为它们是非静态成员函数,所以它们有一个隐含的 this范围。因此,它们具有三个参数。但是,两者都是二元运算符。由于您不能将它们设为静态(那只是因为规则如此规定),因此您必须将它们实现为自由函数。但是,在实现它们时,它们需要访问私有(private)成员,因此您必须让它们成为您类(class)的 friend :

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* 相同,因此在另一个之上实现一个是个好主意。一个常见的习惯用法是实现 *= (和 += 等)作为成员函数(因为它们改变了它们的左参数,对它们来说访问其私有(private)数据是个好主意)和 operator*最重要的是作为非成员(member)。 (通常这比反过来更有效。):

// 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;}

IMO 这是最好的解决方案。


我有。但是,还有一些话要说:

您实现乘法的方式效率低下:

 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;
}

甚至更简洁

 Complex Complex::operator*(const Complex & c) const
{
return Complex(real * c.real, imaginary * c.imaginary);
}

当然,每次乘法只是两次赋值。但是然后 - 你不想在你的图形驱动程序的某些内部循环中使用它。

此外,您的构造函数未按照应有的方式 (TM) 实现。要初始化成员数据,您应该使用初始化列表:

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) , 但忘了包括它,但是有一个 f(const complex&)在范围内,编译器行使它的权利来执行一个用户定义的转换和你的调用 f(4.2)变成 f(Complex(4.2))错误的函数被静默调用。那是非常危险的。

为了避免这种情况,您应该将所有构造函数标记为explicit可以只用一个参数调用:

class Complex {
// ...
explicit Complex(double r, double i = 0)
// ...
};

关于c++ - 将一个常数乘以一个复数 & 运算符重载问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1751869/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com