一、上期回顾

吃透 C++ 内存五分区、new/deletemalloc/free区别、内存泄漏、野指针、堆内存规范管理。今天攻克运算符重载,让自定义结构体 / 类像内置类型一样直接做加减、赋值、输出。

二、运算符重载核心概念

1. 什么是运算符重载

对已有运算符重新定义函数逻辑,适配自定义类,不改变:运算符优先级、结合性、操作数个数。

2. 可重载 / 不可重载

可重载:+ - * / = == != < > << >> [] -> &不可重载::: . .* ?:

3. 两种重载形式

  1. 成员函数重载
  2. 全局函数重载(友元常用)

三、成员函数重载 + 号(自定义点类相加)

#include <iostream>
using namespace std;

class Point
{
private:
    int x, y;
public:
    Point(int a = 0, int b = 0) : x(a), y(b) {}

    // 成员函数重载 +
    Point operator+(const Point& p)
    {
        return Point(x + p.x, y + p.y);
    }

    void show()
    {
        cout << x << " , " << y << endl;
    }
};

int main()
{
    Point p1(1,2);
    Point p2(3,4);
    Point p3 = p1 + p2;
    p3.show();  // 4 , 6
    return 0;
}

四、赋值运算符重载 operator=

默认拷贝是浅拷贝,涉及堆内存必须手动重载 = 实现深拷贝。

class Person
{
private:
    int* age;
public:
    Person(int a)
    {
        age = new int(a);
    }

    // 赋值重载 深拷贝
    Person& operator=(const Person& p)
    {
        // 防止自赋值
        if(this == &p)
            return *this;

        // 释放自身旧空间
        delete age;
        // 重新开辟拷贝
        age = new int(*p.age);
        return *this;
    }

    ~Person()
    {
        delete age;
    }

    void print()
    {
        cout << *age << endl;
    }
};

五、流运算符重载 << >> 必须全局友元

cout << 对象 不能用成员函数重载,只能全局函数 + 友元

class Point
{
private:
    int x, y;
    // 声明友元
    friend ostream& operator<<(ostream& os, const Point& p);
public:
    Point(int a = 0, int b = 0) : x(a), y(b) {}
};

// 重载 <<
ostream& operator<<(ostream& os, const Point& p)
{
    os << "(" << p.x << "," << p.y << ")";
    return os;
}

int main()
{
    Point p(5,6);
    cout << p << endl;
    return 0;
}

同理 >> 输入重载写法一致。


六、关系运算符重载 == / !=

bool operator==(const Point& p)
{
    return x == p.x && y == p.y;
}

七、浅拷贝 vs 深拷贝(面试高频)

浅拷贝

默认编译器生成、逐字节赋值,只拷贝地址,多个对象共享同一块堆内存,析构重复释放崩溃。

深拷贝

重新开辟新堆内存,各自拥有独立空间,互不干扰。触发场景:类中有指针成员、堆内存时,必须:

  1. 自定义拷贝构造
  2. 重载赋值运算符 operator=

八、今日核心总结

  1. 运算符重载不改变优先级、操作数个数
  2. 算术 / 关系运算符常用成员函数重载
  3. << >> 流运算符只能全局友元重载
  4. 有指针堆成员时,必须重载 = + 自定义拷贝构造
  5. 核心目的:让自定义类像内置类型一样运算、赋值、打印

九、课后练习

  1. 写复数类 Complex,重载 + 实现两个复数相加
  2. 重载 << 直接打印复数对象
  3. 给带指针成员的类实现深拷贝赋值重载

更多推荐