运算符重载复数 - 附加功能

Operator overloading complex numbers - additional function

本文关键字:功能 重载 运算符      更新时间:2023-10-16

我试图理解运算符重载的想法,当它们全部组合在一起时,我可能会掌握它的窍门,但是......

我正在努力理解一些使用 + 运算符的代码,该代码已被重载,因此它将添加复杂的数字,代码非常简单。

#include <iostream> 
using namespace std; 

class complex {
  protected:
  double Re, Im;
public:
  complex() : Re(0.0), Im(0.0) {} 
  complex(double Re, double Im) : Re(Re), Im(Im) {} 
  double getRe() const { return Re; }
  double getIm() const { return Im; }
  friend complex operator+(const complex&, const complex&); 
  friend ostream& operator<<(ostream&, const complex&); 
};
complex operator+(const complex& a, const complex& b) {
double r, i;
r = a.getRe() + b.getRe();
i = a.getIm() + b.getIm();
**return complex(r, i);** // *** CAN ANYONE EXPLAIN THIS BIT ? ***
}
ostream& operator<<(ostream& out, const complex &a) {
  out << "(" << a.getRe() << ", " << a.getIm() << ")" << endl;
  return out;
}
int main(void) {
  complex a(1,2), b(3,4), c;
  c = a+b;
  cout << c << endl;

}

我不明白第 23 行到底是做什么的:

return complex(r, i); 

重载添加运算符应该返回一些值,因为已经澄清它应该是复杂类型的值。

这样它看起来像在复杂类中声明,但它与构造函数有关吗?

我的意思是编译器现在会如何,"复杂"类型是什么样子的,因为它是一个类的名称,它与类的构造函数有关吗?

构造函数是否定义了类类型的值?

例如,我们有班级冷狗。

将一个名为 dog 的类类型的值如下所示:

狗的价值

狗类中的构造函数是否定义了值的定义,它的外观,它存储了哪些信息?

  1. 如何重载 ostream 运算符>> (cin( 以便用户可以指定自己的复数值?

谢谢!

注释

complex operator+(const complex& a, const complex& b) {
double r, i;
r = a.getRe() + b.getRe(); // real part of the result
i = a.getIm() + b.getIm(); // imaginary part of the result
return complex(r, i); // you are returning (by value) a complex number formed from r and i
}

在这里,complex(r, i( 创建一个临时的复杂对象(调用构造函数进行初始化(,按值返回将创建另一个临时对象以在调用者中使用。

过载>>声明为

friend istream& operator >> (istream&, complex&);

并定义为:

istream& operator >> (istream& i, complex& c) {
  i >> c.Re >> c.Im;
  return i;
}

运算符重载与构造函数无关(既不是默认的构造函数,也不是复制或移动构造函数;结果可能会被复制,具体取决于签名(。

你基本上告诉计算机如何将一些特定的运算符/操作应用于类的对象(或与其他值的任意组合,具体取决于可用的参数(。

那么它是如何工作的呢?

很简单。假设编译器找到如下结构:

result = first + second;

在这个例子中,我们有两个运算符,所以基本上有两个步骤:

  • operator+()firstsecond.
  • operator=()(赋值运算符(如果已定义(或复制构造函数(来分配result

因此,编译器知道它需要根据firstsecond的类型找到匹配operator+()签名。基本上有两种基本方法可以定义它:

  • 要么作为first班级的一员:... FirstClass::operator+(const SecondClass &secondObject)(我的首选方式(
  • 或者作为具有两个参数的独立函数:... operator+(const FirstClass &firstObject, const SecondClass &secondObject)(对于无法更新的类,例如驻留在标准库(std命名空间(中的类,这是执行此操作的唯一方法(。

我省略了返回类型,因为这些类型实际上取决于您。尽管不建议这样做,但您几乎可以返回任何内容,例如,您甚至不必使用operator+()"添加"。

在复数示例中,编译器将查找... complex::operator+(const complex &other)... operator+(const complex &left, const complex &right)或可能使用隐式强制转换的兼容运算符的任何变体。


对于涉及someInputStream >> myComplexNumber的问题的第二部分 - 如何实现缺少的运算符?

由于您没有直接访问权限来修改输入流类(无论它实际上是什么(,因此您必须在具有两个参数的类外部定义它。应用上面的知识变得非常简单:

std::istream &operator>>(std::istream &input, complex &number);

首先简要解释一下为什么参数中的引用不const:你必须同时修改它们。这与典型的数学惯例相矛盾,例如,当你评估c = a + b时,你既不会修改a也不会修改b。虽然这听起来很奇怪,但事实就是如此。对于流,这是由于流被修改(即使您仅将指针移动到流中的当前位置(。至于复数,这是由于分配正在完成。

在这种情况下,返回类型必须istream &,因为您必须再次返回流对象。这是按照惯例。从理论上讲(如上所述(,您不必这样做,但通过这样做,您可以实现预期的行为,这允许用户链接这些运算符以读取多个内容,例如myStream >> complex1 >> complex2;之类的东西(这基本上计算为 myStream >> complex1;myStream >> complex2 (。

一旦你有了函数的签名,你只需要填写内容,这又是微不足道的:

std::istream &operator>>(std::istream &input, complex &number) {
    input >> number.Re >> number.Im; // query the real and imaginary parts one after the other as doubles (since that's the members' type)
    return input; // return the stream again
}

如果您在理解这个(非常基本的(概念时遇到问题,请记住,运算符只是编写这些重载函数的便捷方法。例如,您可以使用operator+(),而不是使用+

以下两行本质上是相同的:

complexResult = complexNumber1 + complexNumber2;
complexResult = operator+(complexNumber1, complexNumber2);

其他运算符也是如此,如>>||&等。

#include <iostream>
using namespace std;
class complex
{ private :
 int real ;
 int imag ;
 public :
complex(int real=0 , int imag=0)
{
    this->real=real;
    this->imag=imag;
}
complex operator +(complex ob2)
{  complex ob3;
    ob3.real=real + (ob2.real);
    ob3.imag=imag + (ob2.imag);
    return ob3; }
 void out()
{ cout<<real<<" + "<<imag<<"i"<<endl;}
};
int main()
{
int real_1,imag_1;
int real_2,imag_2;
cout<<"real part Enter    ";cin>>real_1;
cout<<"imaginary part Enter  ";cin>>imag_1;
complex ob(real_1,imag_1);
cout<<"real part Enter    ";cin>>real_2;
cout<<"imaginary part Enter  ";cin>>imag_2;
complex ob2(real_2,imag_2);
complex ans;
ans=ob+ob2;
    ans.out();`   `
}