C++ 笔记 运算符重载(面象对象)

运算符重载是 C++ 面向对象编程的重要特性,它让自定义类对象 可以像普通基本数据类型(int、double 等)一样使用+、-、*、/、==、++、--等运算符,大幅提升代码的可读性和简洁性。本文从核心概念、语法、常用运算符重载实现、注意事项全面讲解,帮你快速掌握。

一、运算符重载基础

1. 什么是运算符重载?

本质:给 C++ 原有运算符重新定义功能,使其能处理自定义类的对象。

运算符本质是一种特殊的函数,重载就是定义这个函数;

不创建新运算符,仅对现有运算符重新实现;

不改变运算符的优先级、结合性和操作数个数。

2. 语法格式

作为类成员函数重载(最常用):

cpp 复制代码
返回值类型 operator 运算符(参数列表) {
    // 实现逻辑
}

作为全局函数重载

cpp 复制代码
返回值类型 operator 运算符(参数列表) {
    // 实现逻辑
}

关键字:operator + 要重载的运算符(如operator+operator==

3. 调用方式

两种写法完全等价:

cpp 复制代码
// 隐式调用(简洁,推荐)
对象1 + 对象2;

// 显式调用(本质,编译器底层执行)
对象1.operator+(对象2);

二、常用运算符重载实战

我们以 ** 坐标类(Point)** 为例,实现最常用的运算符重载,包含:+、-、==、!=、前置++、后置++、赋值运算符=

1. 加号运算符 +

实现两个坐标对象相加,返回新的坐标对象。

cpp 复制代码
#include <iostream>
using namespace std;

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

    // 成员函数重载 + :1个参数(右侧运算对象)
    Point operator+(const Point& p) {
        return Point(x + p.x, y + p.y);
    }

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

int main() {
    Point p1(1, 2), p2(3, 4);
    Point p3 = p1 + p2; // 等价 p1.operator+(p2)
    p3.show(); // 输出:x=4, y=6
    return 0;
}

2. 相等 / 不等运算符 == / !=

判断两个对象的成员变量是否相等:

cpp 复制代码
// 在Point类中添加
bool operator==(const Point& p) {
    return x == p.x && y == p.y;
}

bool operator!=(const Point& p) {
    return !(*this == p); // 复用==代码
}

3. 自增运算符 ++(重点区分前置 / 后置)

这是面试高频考点,前置 ++ 和后置 ++ 重载语法不同

cpp 复制代码
// 1. 前置++:返回引用,效率更高
Point& operator++() {
    x++;
    y++;
    return *this;
}

// 2. 后置++:int是占位参数,区分前置,返回临时对象
Point operator++(int) {
    Point temp = *this; // 保存旧值
    x++;
    y++;
    return temp; // 返回旧值
}

4. 赋值运算符 =(必须掌握)

编译器会默认生成赋值运算符,但类中有指针成员时必须手动重载(深拷贝),否则会出现和浅拷贝一样的内存崩溃问题。

cpp 复制代码
// 赋值运算符重载(深拷贝示例)
class Student {
private:
    char* name;
public:
    Student(const char* n) {
        name = new char[strlen(n)+1];
        strcpy(name, n);
    }

    // 重载= 解决浅拷贝问题
    Student& operator=(const Student& s) {
        // 1. 先释放自身原有内存
        if (name != NULL) {
            delete[] name;
            name = NULL;
        }
        // 2. 深拷贝:重新分配内存+复制数据
        name = new char[strlen(s.name)+1];
        strcpy(name, s.name);
        return *this;
    }

    ~Student() {
        delete[] name;
    }
};

5. 左移运算符 <<(全局函数重载)

用于直接输出对象,必须重载为全局函数(友元):

cpp 复制代码
// 类内声明友元
friend ostream& operator<<(ostream& out, const Point& p);

// 类外实现
ostream& operator<<(ostream& out, const Point& p) {
    out << "x=" << p.x << ", y=" << p.y;
    return out; // 支持链式调用:cout << p1 << p2
}

// 使用
cout << p1 << endl;

三、成员函数 VS 全局函数重载

表格

运算符类型 重载方式 参数个数 说明
双目运算符(+ - * / ==) 成员函数 1 个 左侧对象是 this 指针
单目运算符(++ --) 成员函数 0 个 / 1 个(占位) 前置无参,后置 int 占位
左移 / 右移(<<>>) 全局函数(友元) 2 个 不能用成员函数
赋值运算符(=) 成员函数 1 个 只能成员重载

四、不能重载的运算符

C++ 中有 5 个运算符无法重载,牢记即可:

  1. 成员访问运算符:.
  2. 作用域解析符:::
  3. 三目运算符:?:
  4. 长度运算符:sizeof
  5. 类型 id 运算符:typeid

五、运算符重载三大原则

  1. 不改变原有语义:+ 就做加法,不要实现减法逻辑;
  2. 能成员重载就不全局:成员函数可以直接访问私有成员,更简洁;
  3. 有指针必重载 =:赋值运算符必须做深拷贝,防止内存崩溃。

六、完整示例代码

cpp 复制代码
#include <iostream>
using namespace std;

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

    // +
    Point operator+(const Point& p) {
        return Point(x+p.x, y+p.y);
    }

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

    // 前置++
    Point& operator++() {
        x++, y++;
        return *this;
    }

    // 后置++
    Point operator++(int) {
        Point temp = *this;
        x++, y++;
        return temp;
    }

    // 友元声明
    friend ostream& operator<<(ostream& out, const Point& p);
};

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

int main() {
    Point p1(1,2), p2(3,4);
    Point p3 = p1 + p2;
    cout << "p1+p2: " << p3 << endl;

    ++p3;
    cout << "前置++: " << p3 << endl;

    p3++;
    cout << "后置++: " << p3 << endl;

    cout << "p1==p2? " << (p1==p2) << endl;
    return 0;
}

总结

  1. 运算符重载是operator+运算符的函数,让对象支持常规运算;
  2. 成员函数重载最常用,<< / >>必须全局友元重载;
  3. 前置 ++ 返回引用效率高,后置 ++ 用 int 占位区分;
  4. 类有指针成员时,必须重载赋值运算符做深拷贝
  5. 不重载.::?:sizeoftypeid
相关推荐
小陈工2 小时前
Python Web开发入门(一):虚拟环境与依赖管理,从零搭建纯净开发环境
开发语言·前端·数据库·git·python·docker·开源
Yupureki2 小时前
《Linux系统编程》18.线程概念与控制
java·linux·服务器·c语言·jvm·c++
运维行者_2 小时前
金融和电商行业如何使用网络监控保障业务稳定?
开发语言·网络·人工智能·安全·web安全·机器学习·运维开发
csbysj20202 小时前
Eclipse 视图(View)详解
开发语言
CylMK2 小时前
题解:UVA1218 完美的服务 Perfect Service
数据结构·c++·算法·深度优先·图论
zhangzeyuaaa2 小时前
# Python 抽象类(Abstract Class)
开发语言·python
墨^O^2 小时前
并发控制策略与分布式数据重排:锁机制、Redis 分片与 Spark Shuffle 简析
java·开发语言·c++·学习·spark
不被定义的~wolf2 小时前
qt小游戏——坦克大作战
开发语言·qt