1

为什么要有这玩意

定义一个复数类,创建两个复数对象。那么想把这两个复数相加,应该怎么办?

#include <iostream>
#include <stdio.h>

using namespace std;

class Complex {
public:
    int real;
    int imaginary;
    
    Complex(int real, int imaginary) {
        this->real = real;
        this->imaginary = imaginary;
    }
    // 先不看这段;运算符重载,类的成员函数,
//    Complex operator+(const Complex & c) {
//        return Complex(real + c.real, imaginary + c.imaginary);
//    }
};

// 运算符重载,普通函数
Complex operator+(const Complex & c1, const Complex & c2) {
    return Complex(c1.real + c2.real, c1.imaginary + c2.imaginary);
}

int main() {
    // 创建两个复数
    Complex c1(1, 2);
    Complex c2(3, 4);
    // 实部,虚部相加后,再创建新的对象
    Complex c3 = Complex(c1.real + c2.real, c1.imaginary + c2.imaginary);
    cout << "c3.real = " << c3.real << endl;
    cout << "c3.imaginary = " << c3.imaginary << endl;
    // 调用运算符重载,将两个复数对象直接相加
    Complex c4 = c1 + c2;
    cout << "c4.real = " << c4.real << endl;
    cout << "c4.imaginary = " << c4.imaginary << endl;
    return 0;
}

定义

既然叫运算符重载,那么定义的方式就会跟重载类似

  • operator运算符,相当于函数名

  • 形参表,就是参数列表

  • 与返回值类型无关,决定是否构成重载的是函数名和参数列表

普通函数

形参表,必须有两个参数

返回值类型 operator运算符(形参表) {
...... 
}

// 定义成这样,也是可以的,虽然没有意义。
// 我只是定义了两个复数相加的运算,返回类型不一定要是复数
int operator+(const Complex & c1, const Complex & c2) {
    return 1;
}

类的成员函数

  • 参数列表,只能有一个参数

  • 如果普通函数和类的成员函数都存在两个Complex相加的定义,生效的是类的成员函数

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

调用

普通函数

// 两个类型相加就可以了
c1 + c2;
// 返回值才是我们想要的,所以有
Complex c4 = c1 + c2; 
// 以下是上一句的解释,以便于理解赋值运算符重载
// 上一句相当于Complex c4 = operator+(c1, c2);
// operator+是方法名,c1和c2是参数,返回创建的对象给c4

类的成员函数

Complex operator+(const Complex & c) {
    return Complex(real + c.real, imaginary + c.imaginary);
}
// 返回值才是我们想要的,所以有
Complex c3 = c1 + c2; 
// 以下是上一句的解释,以便于理解赋值运算符重载
// 上一句相当于Complex c3 = c1.operator+(c2);
// c1调用它的operator+方法,以c2作用参数,返回创建的对象给c4

赋值运算符重载

为什么要重载它

默认的赋值运算符,是浅拷贝,也就是对于指针变量,只拷贝地址,不复制内容。

#include <iostream>
#include <stdio.h>

using namespace std;

class Student {
    
private:
    int * scores;
public:
    Student (int * scores) : scores(scores) {
        
    }
    
    const int * getScores() {
        return scores;
    }
    
    ~Student() {
        cout << "~Student() --- " << scores << endl;
        delete []scores;
    }
};

int main(){
    int * scores1 = new int[3]{100, 100, 100}; // 学霸
    int * scores2 = new int[3]{10, 10, 10}; // 学渣
    Student s1(scores1);
    Student s2(scores2);
    
    // 地址不同
    cout << s1.getScores() <<endl;
    cout << s2.getScores() <<endl;

    s2 = s1; // 赋予学渣,学霸的力量
    // 地址相同,s1中的scores存储的地址,给我s2的scores
    cout << s1.getScores() <<endl;
    cout << s2.getScores() <<endl;
    // 局部变量回收,析构函数中,s1,s2,都释放了同一个内存空间,因此报错
    return 0;
}

示例

#include <iostream>
#include <stdio.h>

using namespace std;

class Student {
    
private:
    int * scores;
    int scoresLength;
public:
    Student (int * scores, int scoresLength)
    : scores(scores), scoresLength(scoresLength) {
        
    }
    
    const int * getScores() {
        return scores;
    }
    
    Student & operator=(const Student & student) {
        delete []this->scores;
        this->scores = new int[student.scoresLength];
        for (int i = 0; i < student.scoresLength; i++) {
            this->scores[i] = student.scores[i];
        }
        return *this;
    }
    
    ~Student() {
        cout << "~Student() --- " << scores << endl;
        delete []scores;
    }
    
    Student(Student & student) {
        cout << "Student(Student & student)" << endl;
    }
};

int main(){
    int * scores1 = new int[3]{100, 100, 100}; // 学霸
    int * scores2 = new int[3]{10, 10, 10}; // 学渣
    int * scores3 = new int[3]{1, 1, 1}; // 学渣
    Student s1(scores1, 3);
    Student s2(scores2, 3);
    Student s3(scores3, 3);
    
    // 地址不同
    cout << s1.getScores() <<endl;
    cout << s2.getScores() <<endl;
    
    s3 = s2 = s1; // 赋予学渣,学霸的力量
    
    // 地址相同,s1中的scores存储的地址,给我s2的scores
    cout << s1.getScores() <<endl;
    cout << s2.getScores() <<endl;
    cout << s3.getScores() <<endl;
    // 局部变量回收,析构函数中,s1,s2,都释放了同一个内存空间,因此报错
    return 0;
}

问题

返回值类型,一个是对象,一个是引用,为什么?
说不清,道不明啊...

Complex operator+(const Complex & c) {
    return Complex(real + c.real, imaginary + c.imaginary);
}
Student & operator=(Student & student) {
    // ...省略
    return *this;
}

熊一帆
96 声望14 粉丝