跳到主要内容

C++ 运算符重载

提示
  1. 运算符重载概念:在C++中,可以改变用户定义类型(如对象和结构体)的运算符工作方式,这称为运算符重载。例如,可以重定义+运算符来实现两个复数对象的相加。
  2. 运算符重载的语法:要重载一个运算符,需要在类或结构体内定义一个特殊的operator函数。这个函数的返回类型、运算符符号(如+<-)和参数由我们指定。
  3. 一元和二元运算符重载:一元运算符(如++)操作一个操作数,而二元运算符(如+)则操作两个操作数。在重载二元运算符时,调用对象会作为第一个操作数,参数对象作为第二个操作数。

在 C++ 编程中,我们可以改变用户自定义类型(如对象和结构体)的运算符工作方式,这被称为运算符重载。例如,

假设我们创建了三个名为 Complex 的类对象 c1、c2 和 result,用来表示复数。

由于运算符重载允许我们改变运算符的工作方式,我们可以重新定义 + 运算符的工作方式,并通过编写以下代码来实现 c1 和 c2 的复数相加:

result = c1 + c2;

而不是使用类似以下的代码:

result = c1.addNumbers(c2);

这使得我们的代码更直观易懂。

注意: 我们不能对基本数据类型(如 intfloatchar 等)使用运算符重载。

C++ 运算符重载语法

要重载一个运算符,我们需要使用一种特殊的 operator 函数。我们在想要重载运算符的类或结构体内部定义这个函数。

class className {
... .. ...
public:
returnType operator symbol (arguments) {
... .. ...
}
... .. ...
};

这里,

  • returnType 是函数的返回类型。
  • operator 是关键字。
  • symbol 是我们想要重载的运算符。如:+<-++ 等。
  • arguments 是传递给函数的参数。

一元运算符重载

一元运算符只作用于一个操作数。递增运算符 ++ 和递减运算符 -- 是一元运算符的例子。

示例 1:++ 运算符(一元运算符)重载

// 重载前缀 ++

#include <iostream>
using namespace std;

class Count {
private:
int value;

public:

// 构造函数将计数初始化为 5
Count() : value(5) {}

// 重载前缀 ++
void operator ++ () {
++value;
}

void display() {
cout << "计数: " << value << endl;
}
};

int main() {
Count count1;

// 调用 "void operator ++ ()" 函数
++count1;

count1.display();
return 0;
}

输出

计数: 6

这里,当我们使用 ++count1; 时,调用了 void operator ++ () 函数。这会将 count1 对象的 value 属性增加 1。

注意: 当我们重载运算符时,我们可以使其以我们喜欢的任何方式工作。例如,我们可以使用 ++ 将 value 增加 100。

然而,这会使我们的代码变得混乱且难以理解。作为程序员,我们的职责是正确且一致地使用运算符重载。

上述示例仅在 ++ 用作前缀时有效。为了使 ++ 作为后缀有效,我们使用这样的语法:

void operator ++ (int) {
// 代码
}

注意括号内的 int。这是用于后缀形式一元运算符的语法;它不是函数参数。

示例 2:++ 运算符(一元运算符)重载

// 重载前缀和后缀 ++

#include <iostream>
using namespace std;

class Count {
private:
int value;

public:

// 构造函数将计数初始化为 5
Count() : value(5) {}

// 重载前缀 ++
void operator ++ () {
++value;
}

// 重载后缀 ++
void operator ++ (int) {
value++;
}

void display() {
cout << "计数: " << value << endl;
}
};

int main() {
Count count1;

// 调用 "void operator ++ (int)" 函数
count1++;
count1.display();

// 调用 "void operator ++ ()" 函数
++count1;

count1.display();
return 0;
}

输出

计数: 6
计数: 7

示例 2++作为前缀和后缀使用时都有效。但是,如果我们尝试像这样做就不行了:

Count count1, result;

// 错误
result = ++count1;

这是因为我们的操作符函数的返回类型是void。我们可以通过将Count作为操作符函数的返回类型来解决这个问题。

// 当++作为前缀使用时返回Count

Count operator ++ () {
// 代码
}

// 当++作为后缀使用时返回Count

Count operator ++ (int) {
// 代码
}

示例 3:从操作符函数返回值(++操作符)

#include <iostream>
using namespace std;

class Count {
private:
int value;

public:
// 构造函数初始化计数为5
Count() : value(5) {}

// 重载++作为前缀时
Count operator ++ () {
Count temp;

// 这里,value是调用对象的value属性
temp.value = ++value;

return temp;
}

// 重载++作为后缀时
Count operator ++ (int) {
Count temp;

// 这里,value是调用对象的value属性
temp.value = value++;

return temp;
}

void display() {
cout << "计数: " << value << endl;
}
};

int main() {
Count count1, result;

// 调用"Count operator ++ ()"函数
result = ++count1;
result.display();

// 调用"Count operator ++ (int)"函数
result = count1++;
result.display();

return 0;
}

输出

计数: 6
计数: 6

这里,我们对前缀操作符重载使用了以下代码:

// 重载++作为前缀
Count operator ++ () {
Count temp;

// 这里,value是调用对象的value属性
temp.value = ++value;

return temp;
}

后缀操作符重载的代码也类似。请注意,我们创建了一个临时对象temp并将其值返回给操作符函数。

另外,请注意代码

temp.value = ++value;

变量value属于main()中的count1对象,因为count1是调用该函数的对象,而temp.value属于temp对象。

二元操作符重载

二元操作符作用于两个操作数。例如,

result = num + 9;

这里,+是一个二元操作符,它作用于操作数num和9

当我们通过使用代码:

obj3 = obj1 + obj2;

为用户定义的类型重载二元操作符时,操作符函数是使用obj1对象调用的,而obj2作为参数传递给函数。

示例 4:C++二元操作符重载

// C++程序重载二元操作符+
// 该程序将两个复数相加

#include <iostream>
using namespace std;

class Complex {
private:
float real;
float imag;

public:
// 构造函数初始化real和imag为0
Complex() : real(0), imag(0) {}

void input() {
cout << "分别输入实部和虚部: ";
cin >> real;
cin >> imag;
}

// 重载+操作符
Complex operator + (const Complex& obj) {
Complex temp;
temp.real = real + obj.real;
temp.imag = imag + obj.imag;
return temp;
}

void output() {
if (imag < 0)
cout << "输出复数: " << real << imag << "i";
else
cout << "输出复数: " << real << "+" << imag << "i";
}
};

int main() {
Complex complex1, complex2, result;

cout << "输入第一个复数:\n";
complex1.input();

cout << "输入第二个复数:\n";
complex2.input();

// complex1调用操作符函数
// complex2作为参数传递给函数
result = complex1 + complex2;
result.output();

return 0;
}

输出

输入第一个复数:
分别输入实部和虚部: 9 5
输入第二个复数:
分别输入实部和虚部

: 7 6
输出复数: 16+11i

在这个程序中,操作符函数是:

Complex operator + (const Complex& obj) {
// 代码
}

我们也可以这样写这个函数:

Complex operator + (Complex obj) {
// 代码
}

然而,

  • 使用&通过引用complex2对象而不是在操作符函数内部制作一个重复对象,使我们的代码更高效。
  • 使用const被认为是一种好的做法,因为它阻止操作符函数修改complex2。

C++ 二元操作符重载

C++操作符重载需记住的事情

  1. C++中的两个操作符=&已经默认重载。例如,要复制同一类的对象,我们可以直接使用=操作符。我们不需要创建操作符函数。

  2. 操作符重载不能改变操作符的优先级和结合性。然而,如果我们想改变评估顺序,应该使用括号。

  3. 有4个操作符在C++中不能重载。它们是:

  4. ::(作用域解析)

  5. .(成员选择)

  6. .*(通过指向函数的指针的成员选择)

  7. ?:(三元操作符)

访问这些页面以了解更多: