什么是运算符重载
运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型,本质上是函数重载。以下为您详细介绍:
实现原理与方式
- 原理:把指定的运算表达式转化为对运算符函数的调用,将运算符对象转化为运算符函数的实参,然后在编译过程中,根据实参的类型确定需要调用的函数 。其函数名字由关键字 operator 及其紧跟的运算符组成,比如重载 + 运算符的函数名为 operator+ 。
- 实现方式
- 成员函数重载:将运算符重载为类的成员函数,此时函数的参数个数比该运算符实际操作数少1 个(一元运算符除外),因为其中一个操作数就是调用该函数的对象本身(通过 this 指针隐式传递) 。例如在C++中定义一个复数类 Complex ,重载 + 运算符实现复数相加:
class Complex {
private:
double real;
double imag;
public:
Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}
Complex operator+(const Complex& other) {
return Complex(real + other.real, imag + other.imag);
}
};
- 友元函数重载:通过 friend 关键字声明为类的友元函数来重载运算符。友元函数不属于类的成员函数,但能访问类的私有成员。对于双目运算符重载为友元函数,参数个数与操作数个数相同,这样可以使用交换律。比如:
class Complex {
private:
double real;
double imag;
public:
Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}
friend Complex operator+(const Complex& c1, const Complex& c2);
};
Complex operator+(const Complex& c1, const Complex& c2) {
return Complex(c1.real + c2.real, c1.imag + c2.imag);
}
- 普通函数重载:在类外定义普通函数进行运算符重载,同样要求至少有一个操作数是用户自定义类型。例如:
class Complex {
public:
double real;
double imag;
Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}
};
Complex operator+(const Complex& c1, const Complex& c2) {
return Complex(c1.real + c2.real, c1.imag + c2.imag);
}
可重载运算符与限制
- 可重载运算符 :在C++中,除成员访问运算符“.”、作用域运算符“::”、 sizeof 运算符和三目运算符“?:”等少数运算符外,大多数运算符都可重载 。包括算术运算符(+、-、*、/ 等)、位操作运算符(&、|、~ 等)、逻辑运算符(! 等)、比较运算符(<、>、== 等)、赋值运算符(=、+=、-= 等)以及其他运算符(()、[]、-> 等 )。
- 限制
- 重载后的运算符不能改变其优先级和结合性,也不能改变操作数的个数及语法结构 。
- 不能改变运算符用于内部类型对象的含义 。
- 运算符重载是针对新类型数据的实际需要对原有运算符进行适当改造,重载功能应与原有功能类似 。
- 重载运算符的函数不能有默认参数,否则会改变运算符参数个数 。
- 重载的运算符操作数至少有一个是用户自定义类型 。
应用场景
- 自定义数据类型运算:比如自定义的复数类、矩阵类等,通过重载运算符实现这些自定义类型对象间的加减乘除等运算,让代码更直观、易读 。例如对于矩阵类,重载 + 运算符实现矩阵相加:
class Matrix {
// 矩阵相关成员变量
int rows, cols;
int** data;
public:
Matrix(int r, int c) : rows(r), cols(c) {
data = new int*[rows];
for (int i = 0; i < rows; ++i) {
data[i] = new int[cols];
}
}
Matrix operator+(const Matrix& other) {
Matrix result(rows, cols);
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
result.data[i][j] = data[i][j] + other.data[i][j];
}
}
return result;
}
// 其他成员函数
};
- 输入输出操作:通过重载输入流运算符 >> 和输出流运算符 << ,方便自定义类型对象的输入输出。比如:
class Complex {
private:
double real;
double imag;
public:
Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) {}
friend std::istream& operator>>(std::istream& in, Complex& c);
friend std::ostream& operator<<(std::ostream& out, const Complex& c);
};
std::istream& operator>>(std::istream& in, Complex& c) {
in >> c.real >> c.imag;
return in;
}
std::ostream& operator<<(std::ostream& out, const Complex& c) {
out << "(" << c.real << ", " << c.imag << ")";
return out;
}
这样就可以像使用基本数据类型一样,用 cin >> complexObj 和 cout << complexObj 来输入输出复数对象。