文章目录
- 一、重载运算符
- 1. 运算符重载的规则
- 2. 示例:重载加法运算符`+`
- 3. 注意事项
- 二、可重载运算符/不可重载运算符
- 1. 可重载的运算符
- 2. 不可重载的运算符
- 3. 注意事项
- 三、重载函数
- 1. 函数重载的基本规则
- 2. 示例
- 3. 注意事项
- 四、相关链接
一、重载运算符
在C++中,重载运算符允许你为自定义类型(如类)的实例定义运算符的行为。这意呀着你可以像使用内置类型(如int或float)那样使用你的自定义类型进行算术运算、比较、赋值等操作。重载运算符是通过在类内部或外部定义成员函数或非成员函数来实现的。
1. 运算符重载的规则
- 不能改变运算符的优先级:重载后的运算符优先级和结合性保持不变。
- 不能改变运算符的操作数个数:例如,你不能将二元运算符重载为单目运算符。
- 不能创建新的运算符:你只能重载C++中已有的运算符。
- 不能重载所有的运算符:例如,
.
、.*
、::
、?:
、sizeof
和typeid
等运算符不能被重载。 - 重载的运算符可以定义为成员函数或非成员函数:但是,某些运算符(如赋值运算符
=
、下标运算符[]
、函数调用运算符()
、成员访问运算符->*
和->
)只能作为成员函数重载。
2. 示例:重载加法运算符+
假设我们有一个简单的Point
类,表示二维空间中的点,我们想要重载加法运算符,以便可以将两个Point
对象相加,得到一个新的Point
对象,其坐标是这两个点坐标的和。
#include <iostream>
class Point {
public:
int x, y;
// 构造函数
Point(int x = 0, int y = 0) : x(x), y(y) {}
// 重载加法运算符
Point operator+(const Point& rhs) const {
return Point(x + rhs.x, y + rhs.y);
}
// 输出函数,用于演示
void print() const {
std::cout << "(" << x << ", " << y << ")" << std::endl;
}
};
int main() {
Point p1(1, 2);
Point p2(3, 4);
Point p3 = p1 + p2; // 使用重载的加法运算符
p3.print(); // 输出: (4, 6)
return 0;
}
在这个例子中,operator+
是一个成员函数,它接受一个Point
类型的常量引用作为参数(rhs
),并返回一个新的Point
对象,该对象的坐标是调用对象(*this
)和参数对象(rhs
)的坐标之和。注意,我们在这里将operator+
定义为const
成员函数,因为我们没有修改调用对象的状态。
3. 注意事项
- 当重载运算符时,考虑其语义是否适合你的类。
- 运算符重载应该保持直观和易于理解。
- 某些运算符(如赋值运算符
=
)可能需要返回对自身的引用(*this
),以便支持链式调用。 - 运算符重载可能会引入额外的性能开销,因为它们是函数调用。然而,在大多数情况下,这种开销是可以接受的。
二、可重载运算符/不可重载运算符
在C++中,大部分运算符都可以被重载,但也有一些运算符是不能被重载的。这些运算符的不可重载性通常是因为它们与语言的底层机制紧密相关,或者是因为它们的行为在语义上不应该被改变。
1. 可重载的运算符
大部分C++中的运算符都可以被重载,包括:
- 算术运算符:
+
、-
、*
、/
、%
(取模)、++
(前缀和后缀)、--
(前缀和后缀) - 关系运算符:
==
、!=
、<
、<=
、>
、>=
- 逻辑运算符:
&&
、||
、!
(但请注意,这些运算符通常通过成员函数重载时并不直观,因为它们期望两个操作数,而成员函数重载通常只涉及一个显式的操作数——*this指针所指向的对象) - 赋值运算符:
=
、+=
、-=
、*=
、/=
、%=
- 位运算符:
&
、|
、^
、~
、<<
、>>
- 成员访问运算符:
->*
和->
(注意,这些运算符只能作为成员函数重载) - 下标运算符:
[]
(也只能作为成员函数重载) - 函数调用运算符:
()
(也只能作为成员函数重载,用于重载对象的调用方式) - 逗号运算符:
,
(不常用,但技术上可以重载) - 转换运算符(类型转换运算符):用于定义对象如何被隐式或显式地转换为其他类型。
2. 不可重载的运算符
以下运算符在C++中是不可重载的:
.
成员访问运算符.*
成员指针访问运算符::
作用域解析运算符?:
条件运算符(三元运算符)sizeof
运算符(用于获取对象或类型的大小)typeid
运算符(用于在运行时获取对象的类型信息)const_cast
、static_cast
、dynamic_cast
、reinterpret_cast
等类型转换运算符(尽管它们看起来像是运算符,但实际上它们是特殊的语言构造,用于执行类型转换)
3. 注意事项
- 当重载运算符时,通常应该保持运算符的语义不变,即重载后的运算符应该执行与原始运算符相似的操作,只是针对自定义类型。
- 重载运算符时,可以通过成员函数或非成员函数来实现。但是,某些运算符(如赋值运算符
=
、下标运算符[]
、函数调用运算符()
等)只能作为成员函数重载。 - 重载运算符时,可以定义返回类型,但通常应该返回与操作数类型相同(或兼容)的类型,除非有特殊的理由需要返回不同类型的对象。
- 运算符重载可以提高代码的可读性和易用性,但过度使用或不当使用可能会导致代码难以理解和维护。因此,在决定重载运算符之前,应该仔细考虑是否真的需要这样做。
三、重载函数
C++ 中的函数重载允许在同一个作用域内定义多个同名的函数,只要这些函数的参数列表(参数的类型、顺序或数量)不同即可。这样,你可以使用同一个函数名来执行不同的任务,具体执行哪个任务取决于调用函数时提供的参数。
1. 函数重载的基本规则
- 函数名必须相同:重载的函数必须具有相同的名称。
- 参数列表必须不同:这包括参数的类型、顺序或数量。仅通过返回类型的不同来区分重载函数是不允许的。
- 函数可以具有不同的返回类型,但返回类型不能作为重载的依据。
- 函数可以有不同的访问修饰符(如
public
、protected
和private
),但这通常不是重载的考虑因素,因为重载是在编译时根据函数名和参数列表来确定的。 - 可以声明为
const
的函数和未声明为const
的函数版本可以重载(当它们属于同一类时,并且一个作用于常量对象,另一个作用于非常量对象)。
2. 示例
下面是一个简单的函数重载示例,展示了如何根据不同的参数类型来重载print
函数。
#include <iostream>
#include <string>
// 第一个 print 函数,用于整数
void print(int i) {
std::cout << "Printing int: " << i << std::endl;
}
// 第二个 print 函数,用于浮点数
void print(double f) {
std::cout << "Printing float: " << f << std::endl;
}
// 第三个 print 函数,用于字符串
void print(const std::string& str) {
std::cout << "Printing string: " << str << std::endl;
}
int main() {
print(5); // 调用第一个 print 函数
print(500.263); // 调用第二个 print 函数
print("Hello"); // 调用第三个 print 函数
return 0;
}
3. 注意事项
- 当编译器遇到对函数的调用时,它会根据提供的参数来查找匹配的重载函数。如果找不到完全匹配的重载函数,编译器将尝试通过类型转换来寻找合适的重载函数(如果可能的话)。
- 如果存在多个重载函数都匹配给定的参数,但其中一个函数比其他函数更具体(即,它可以更精确地匹配给定的参数类型,而不需要类型转换),则编译器将选择这个更具体的函数。
- 如果编译器无法确定哪个重载函数是最佳选择(例如,如果存在两个同样“好”的候选函数),则会报告一个编译时错误,称为“重载解析不明确”。
- 成员函数重载时,隐式的
this
指针(指向调用对象的指针)也参与重载解析,但它不直接作为重载的依据。然而,它会影响如何通过成员函数访问其他成员函数或成员变量,这可能间接影响重载解析的结果。
四、相关链接
- Visual Studio Code下载地址
- Sublime Text下载地址
- 「C++系列」C++简介、应用领域
- 「C++系列」C++ 基本语法
- 「C++系列」C++ 数据类型
- 「C++系列」C++ 变量类型
- 「C++系列」C++ 变量作用域
- 「C++系列」C++ 常量知识点-细致讲解
- 「C++系列」C++ 修饰符类型
- 「C++系列」一篇文章说透【存储类】
- 「C++系列」一篇文章讲透【运算符】
- 「C++系列」循环
- 「C++系列」判断
- 「C++系列」函数/内置函数
- 「C++系列」数字/随机数
- 「C++系列」数组
- 「C++系列」字符串
- 「C++系列」指针
- 「C++系列」引用
- 「C++系列」日期/时间
- 「C++系列」输入/输出
- 「C++系列」数据结构
- 「C++系列」vector 容器
- 「C++系列」类/对象
- 「C++系列」继承