C++ 运算符重载:自定义类型的运算扩展
💡 :掌握运算符重载的核心语法与规则,能够为自定义类型重载常用运算符,实现类对象的灵活运算。 💡 :运算符重载的基本形式、成员函数与全局函数重载的区别、常见运算符的重载实现、禁止重载的运算符。
C++ 运算符重载的概念、语法及实现。内容包括成员函数与全局函数重载的区别,二元、一元、关系及输入输出运算符的重载示例。重点讲解了前置与后置 ++ 的区别,赋值运算符深拷贝处理,以及禁止重载的运算符。通过复数运算实战案例展示了综合应用,并总结了开发规范,旨在帮助开发者为自定义类型扩展运算能力,提升代码可读性与一致性。

💡 :掌握运算符重载的核心语法与规则,能够为自定义类型重载常用运算符,实现类对象的灵活运算。 💡 :运算符重载的基本形式、成员函数与全局函数重载的区别、常见运算符的重载实现、禁止重载的运算符。
✅ 结论:运算符重载是 C++ 静态多态的重要体现,允许为自定义类型(如类、结构体)重新定义运算符的行为,让自定义对象可以像内置类型一样使用运算符。
运算符重载的核心价值:
⚠️ 注意事项:运算符重载不会改变运算符的优先级和结合性,也不会改变运算符的操作数个数。
运算符重载的本质是函数重载,分为成员函数重载和全局函数重载两种形式。
将运算符重载函数定义为类的成员函数,语法格式如下:
class 类名 {
public:
返回值类型 operator 运算符 (参数列表) {
// 自定义运算逻辑
}
};
++、--)作为成员函数时,没有参数+、-)作为成员函数时,只有一个参数,表示运算符右侧的操作数将运算符重载函数定义为全局函数,语法格式如下:
返回值类型 operator 运算符 (参数列表) {
// 自定义运算逻辑
}
+ 为例以自定义 Point 类为例,重载 + 运算符实现两个点的坐标相加。
+ 运算符#include <iostream>
using namespace std;
class Point {
public:
int x, y;
// 构造函数
Point(int x = 0, int y = 0) : x(x), y(y) {}
// 成员函数重载 + 运算符
Point operator+(const Point& p) {
return Point(this->x + p.x, this->y + p.y);
}
// 打印点坐标
void print() {
cout << "(" << x << ", " << y << ")" << endl;
}
};
int main() {
Point p1(1, 2), p2(3, 4);
Point p3 = p1 + p2; // 等价于 p1.operator+(p2)
p3.print(); // 输出 (4, 6)
return 0;
}
+ 运算符#include <iostream>
using namespace std;
class Point {
public:
int x, y;
// 构造函数
Point(int x = 0, int y = 0) : x(x), y(y) {}
// 打印点坐标
void print() {
cout << "(" << x << ", " << y << ")" << endl;
}
// 声明友元函数
friend Point operator+(const Point& p1, const Point& p2);
};
// 全局函数重载 + 运算符
Point operator+(const Point& p1, const Point& p2) {
return Point(p1.x + p2.x, p1.y + p2.y);
}
int main() {
Point p1(1, 2), p2(3, 4);
Point p3 = p1 + p2; // 等价于 operator+(p1, p2)
p3.print(); // 输出 (4, 6)
return 0;
}
++ 为例一元运算符分为前置 ++ 和后置 ++,二者的重载方式有区别。
++ 运算符重载前置 ++ 表示先自增,再使用,重载时没有参数。
#include <iostream>
using namespace std;
class Counter {
private:
int count;
public:
Counter(int c = 0) : count(c) {}
// 成员函数重载前置 ++
Counter& operator++() {
this->count++;
return *this; // 返回自增后的对象,支持链式操作
}
void show() {
cout << "计数:" << count << endl;
}
};
int main() {
Counter c(5);
++c; // 等价于 c.operator++()
c.show(); // 输出 计数:6
Counter c2 = ++c;
c2.show(); // 输出 计数:7
return 0;
}
++ 运算符重载后置 ++ 表示先使用,再自增,重载时需要添加一个占位参数 int 区分前置版本。
#include <iostream>
using namespace std;
class Counter {
private:
int count;
public:
Counter(int c = 0) : count(c) {}
// 成员函数重载后置 ++
Counter operator++(int) {
Counter temp = *this; // 保存当前对象状态
this->count++;
return temp; // 返回自增前的对象
}
void show() {
cout << "计数:" << count << endl;
}
};
int main() {
Counter c(5);
Counter c2 = c++; // 等价于 c.operator++(0)
c.show(); // 输出 计数:6
c2.show(); // 输出 计数:5
return 0;
}
== 为例重载关系运算符(==、!=、<、> 等),实现自定义对象的比较逻辑。
#include <iostream>
#include <string>
using namespace std;
class Student {
private:
string name;
int id;
public:
Student(string name, int id) : name(name), id(id) {}
// 成员函数重载 == 运算符
bool operator==(const Student& s) {
return this->id == s.id; // 按学号判断是否为同一学生
}
string getName() {
return name;
}
};
int main() {
Student s1("张三", 2024001);
Student s2("李四", 2024002);
Student s3("张三", 2024001);
if (s1 == s3) {
cout << s1.getName() << " 和 " << s3.getName() << " 是同一学生" << endl;
} else {
cout << "不是同一学生" << endl;
}
if (s1 == s2) {
cout << "是同一学生" << endl;
} else {
cout << s1.getName() << " 和 " << s2.getName() << " 不是同一学生" << endl;
}
return 0;
}
<< 和 >><< 和 >> 运算符通常需要全局函数 + 友元的方式重载,因为左侧操作数是 ostream 或 istream 对象。
#include <iostream>
#include <string>
using namespace std;
class Person {
private:
string name;
int age;
public:
Person(string name = "", int age = 0) : name(name), age(age) {}
// 声明友元函数,重载 << 运算符
friend ostream& operator<<(ostream& os, const Person& p);
// 声明友元函数,重载 >> 运算符
friend istream& operator>>(istream& is, Person& p);
};
// 重载 << 运算符,用于输出对象
ostream& operator<<(ostream& os, const Person& p) {
os << "姓名:" << p.name << ",年龄:" << p.age;
return os; // 返回 os,支持链式输出
}
// 重载 >> 运算符,用于输入对象
istream& operator>>(istream& is, Person& p) {
is >> p.name >> p.age;
return is; // 返回 is,支持链式输入
}
int main() {
Person p;
cout << "请输入姓名和年龄:" << endl;
cin >> p; // 等价于 operator>>(cin, p)
cout << "你输入的信息:" << p << endl; // 等价于 operator<<(cout, p)
return 0;
}
以下运算符不允许重载,使用时需注意:
..*::?:#以下运算符只能通过类的成员函数重载,不能使用全局函数:
=()[]->= 的注意事项赋值运算符 = 是类的默认成员函数,编译器会自动生成一个浅拷贝版本。当类中包含指针成员时,必须手动重载 = 实现深拷贝,避免浅拷贝导致的内存泄漏。
#include <iostream>
#include <cstring>
using namespace std;
class String {
private:
char* str;
public:
// 构造函数
String(const char* s = "") {
str = new char[strlen(s) + 1];
strcpy(str, s);
}
// 析构函数
~String() {
delete[] str;
}
// 重载赋值运算符 =,实现深拷贝
String& operator=(const String& s) {
if (this == &s) { // 防止自赋值
return *this;
}
// 释放当前对象的内存
delete[] str;
// 分配新内存并拷贝数据
str = new char[strlen(s.str) + 1];
strcpy(str, s.str);
return *this; // 支持链式赋值
}
void show() {
cout << str << endl;
}
};
int main() {
String s1("Hello C++");
String s2;
s2 = s1; // 调用重载的 = 运算符
s2.show(); // 输出 Hello C++
return 0;
}
⚠️ 核心注意点:重载赋值运算符时,必须返回 *this 的引用,否则无法支持链式赋值(如 a = b = c)。
💡 需求:设计一个 Complex 类表示复数,重载 +、-、*、<< 运算符,实现复数的加减乘运算和输出功能。
real 和虚部 imag 两个成员变量+:(a+bi)+(c+di)=(a+c)+(b+d)i-:(a+bi)-(c+di)=(a-c)+(b-d)i*:(a+bi)*(c+di)=(ac-bd)+(ad+bc)i<<:输出复数的标准格式#include <iostream>
using namespace std;
class Complex {
private:
double real; // 实部
double imag; // 虚部
public:
// 构造函数
Complex(double real = 0, double imag = 0) : real(real), imag(imag) {}
// 成员函数重载 + 运算符
Complex operator+(const Complex& c) {
return Complex(this->real + c.real, this->imag + c.imag);
}
// 成员函数重载 - 运算符
Complex operator-(const Complex& c) {
return Complex(this->real - c.real, this->imag - c.imag);
}
// 成员函数重载 * 运算符
Complex operator*(const Complex& c) {
double r = this->real * c.real - this->imag * c.imag;
double i = this->real * c.imag + this->imag * c.real;
return Complex(r, i);
}
// 友元函数重载 << 运算符
friend ostream& operator<<(ostream& os, const Complex& c);
};
// 实现 << 运算符重载
ostream& operator<<(ostream& os, const Complex& c) {
if (c.imag >= 0) {
os << c.real << " + " << c.imag << "i";
} else {
os << c.real << " - " << -c.imag << "i";
}
return os;
}
int main() {
Complex c1(3, 4), c2(1, -2);
Complex c3 = c1 + c2;
Complex c4 = c1 - c2;
Complex c5 = c1 * c2;
cout << "c1 = " << c1 << endl;
cout << "c2 = " << c2 << endl;
cout << "c1 + c2 = " << c3 << endl;
cout << "c1 - c2 = " << c4 << endl;
cout << "c1 * c2 = " << c5 << endl;
return 0;
}
c1 = 3 + 4i
c2 = 1 - 2i
c1 + c2 = 4 + 2i
c1 - c2 = 2 + 6i
c1 * c2 = 11 - 2i
+=、-=),优先使用成员函数重载<< 和 >> 运算符必须使用全局函数 + 友元的方式重载= 实现深拷贝✅ 运算符重载的本质是函数重载,分为成员函数和全局函数两种实现方式。
✅ 运算符重载不会改变运算符的优先级、结合性和操作数个数。
✅ 部分运算符有固定的重载方式,如 = 必须用成员函数,<< 必须用全局友元函数。
✅ 合理使用运算符重载可以简化代码、统一风格,是 C++ 面向对象编程的重要技能。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML 转 Markdown 互为补充。 在线工具,Markdown 转 HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML 转 Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online