9.7c++学习记录(7)

一.类运算符重载

1.

#include <iostream>
using namespace std;
class Complex {
private:
    double r, i;

public:
    Complex(double R = 0, double I = 0) : r(R), i(I) {};
    Complex operator+(Complex b);
    Complex operator-(Complex b);
    Complex operator*(Complex b);
    Complex operator/(Complex b);
    void display();
};

Complex Complex::operator+(Complex b) { return Complex(r + b.r, i + b.i); }
Complex Complex::operator-(Complex b) { return Complex(r - b.r, i - b.i); }
//求复数相乘的算法
Complex Complex::operator*(Complex b) {
    Complex t;
    t.r = r * b.r - i * b.i;
    t.i = r * b.i + i * b.r;
    return t;
}
//求复数相除的算法
Complex Complex::operator/(Complex b) {
    Complex t;
    double x;
    x = 1 / (b.r * b.r + b.i * b.i);
    t.r = x * (r * b.r + i * b.i);
    t.i = x * (i * b.r - r * b.i);
    return t;
}
void Complex::display() {
    cout << r;
    if (i > 0)
        cout << "+";
    if (i != 0)
        cout << i << "i" << endl;
    //}display();
};

int main(void) {
    Complex c1(1, 2), c2(3, 4), c3, c4, c5, c6;
    Complex a, b(2, 3);
    a = b + 2; //正确
    // a=2+b;       			//错误
    a.display();
    c3 = c1 + c2;
    c4 = c1 - c2;
    c5 = c1 * c2;
    c6 = c1 / c2;
    c1.display();
    c2.display();
    c3.display();
    c4.display();
    c5.display();
    c6.display();

    return 0;
}

2..Complex(double R = 0, double I = 0) : r(R), i(I) {};与 Complex(double R = 0, double I = 0) {r=R ;i=I;}等价吗

这两段代码不完全等价。

第一段代码是使用成员初始化列表来初始化类的成员变量 r 和 i。这是 C++ 中的一种初始化方式,可以在构造函数中使用它来指定如何初始化类的成员变量。在这种情况下,构造函数会将参数 R 和 I 的值分别传递给成员变量 r 和 i

第二段代码是在构造函数中使用赋值运算符来初始化类的成员变量。在这种情况下,构造函数会将参数 R 和 I 的值分别赋给局部变量 R 和 I,然后再将这些局部变量的值赋给成员变量 r 和 i

这两段代码的主要区别在于初始化的方式。成员初始化列表可以直接将参数的值传递给成员变量,而赋值运算符则需要先创建局部变量,然后再将局部变量的值赋给成员变量。在性能方面,成员初始化列表通常比赋值运算符更高效,因为它可以直接将参数的值传递给成员变量,而不需要创建额外的局部变量。

因此,这两段代码不完全等价,推荐使用成员初始化列表来初始化类的成员变量。

3.Complex Complex::operator+(Complex b) { return Complex(r + b.r, i + b.i); }和 Complex Complex::operator+(Complex b,Complex c) { return Complex(r + b.r, i + b.i); }有什么区别?

这两个函数在功能上非常相似,都是实现两个复数的加法。然而,它们的参数列表是不同的。

第一个函数只有一个参数,即另一个Complex对象b。它返回的是当前对象(this)和b的加法结果。

第二个函数有两个参数,即两个Complex对象bc。它返回的是bc的加法结果。

因此,这两个函数的主要区别在于它们接收的参数数量和类型。第一个函数只接收一个Complex对象作为参数,而第二个函数接收两个Complex对象作为参数。

另外,注意到在你的代码中,无论哪个函数,它们都使用了相同的返回类型和构造函数的参数。这意味着,你可以将加法的结果封装在一个新的Complex对象中并返回。

4.为什么上述代码里使用a=2+b会报错

上述代码中,如果使用a=2+b会报错,是因为把2当成了int类型,所以改成(Complex)2即可。

二.操作符重载与友元关系

1.

#include <iostream>

class Complex {
private:
    double r, i;

public:
    Complex(double R = 0, double I = 0) : r(R), i(I) {};
    friend Complex operator+(Complex a, Complex b);
    friend Complex operator-(Complex a, Complex b);
    friend Complex operator*(Complex a, Complex b);
    friend Complex operator/(Complex a, Complex b);

    friend Complex operator+(Complex a, double b) {
        return Complex(a.r + b, a.i);
    }
    friend Complex operator+(double a, Complex b) {
        return Complex(a + b.r, b.i);
    }

    void display();
};

Complex operator+(Complex a, Complex b) {
    return Complex(a.r + b.r, a.i + b.i);
}
Complex operator-(Complex a, Complex b) {
    return Complex(a.r - b.r, a.i - b.i);
}
Complex operator*(Complex a, Complex b) {
    Complex t;
    t.r = a.r * b.r - a.i * b.i;
    t.i = a.r * b.i + a.i * b.r;
    return t;
}
Complex operator/(Complex a, Complex b) {
    Complex t;
    double x;
    x = 1 / (b.r * b.r + b.i * b.i);
    t.r = x * (a.r * b.r + a.i * b.i);
    t.i = x * (a.i * b.r - a.r * b.i);
    return t;
}

void Complex::display() {
    std::cout << r;
    if (i > 0)
        std::cout << "+";
    if (i != 0)
        std::cout << i << "i" << std::endl;
}
int main(void) {
    Complex c1(1, 2), c2(3, 4), c3, c4, c5, c6;
    Complex a, b(2, 3);
    Complex a1 = b + 2;
    Complex a2 = 2 + b;
    a1.display();
    a2.display();
    c3 = c1 + c2;
    c4 = c1 - c2;
    c5 = c1 * c2;
    c6 = c1 / c2;
    c1.display();
    c2.display();
    c3.display();
    c4.display();
    c5.display();
    c6.display();

    return 0;
}

这个更像我们平时理解的加减乘除关系。而且支持不同类型之间的运算。

三.=运算符重载

// 引入iostream库,这个库让我们可以使用cin和cout来进行输入和输出。  
#include <iostream>  
  
// 使用命名空间std,这样可以让我们使用标准库中的符号,而不用加std::前缀。  
using namespace std;  
  
// 定义一个名为X的类。  
class X {  
public:  
  // 重载赋值运算符。这是成员函数,因此它的第一个参数是隐式的类实例引用。  
  // 参数是常量引用,这意味着我们只能通过这个引用访问常量对象,不能修改它。  
  X &operator=(const X &x) {  
    // 输出字符串"a:",表示我们正在使用重载的赋值运算符。  
    cout << "a:";  
    // 返回当前对象的引用。这是非常重要的,因为它允许链式赋值。  
    return *this;  
  };  
};  
  
// 主函数,程序的执行从这里开始。  
int main() {  
  // 创建三个X类的对象。  
  X obj1, obj2, obj3;  
    
  // 使用重载的赋值运算符将obj2的值赋给obj1。这会调用我们之前定义的赋值运算符函数。  
  obj1 = obj2;          //调用重载“=”  
    
  // 使用成员函数语法再次调用赋值运算符。  
  obj1.operator=(obj2); //调用重载“=”  
    
  // 同时将obj3的值赋给obj2和obj1,也是调用我们重载的赋值运算符。  
  obj1 = obj2 = obj3;   //调用重载“=”  
    
  return 0;             // 返回0表示程序正常结束。  
}

四. []与() 运算符重载

#include <iostream>
using namespace std;
class X {
public:
  int operator()(int i = 0) {
    cout << "X::operator(" << i << ")" << endl;
    return i;
  };
  int operator()(int i, int j) {
    cout << "X::operator(" << i << "," << j << ")" << endl;
    return i;
  };
  int operator[](int i) {
    cout << "X::operator[" << i << "]" << endl;
    return i;
  };
  int operator[](char *cp) {
    cout << "X::operator[" << cp << "]" << endl;
    return 0;
  };
};
int main(void) {
  X obj;
  int i = obj(obj(1), 2);
  int a = obj[i];
  int b = obj["abcd"];
  cout << "a=" << a << endl;
  cout << "b=" << b << endl;
  
}

运行的时候会报错,要把int operator[](char *cp) 改成int operator[](const char *cp)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值