Appearance
C++ 重载运算符和重载函数
重载是 C++ 的一个重要特性,它允许为同一个函数名或运算符定义多个版本,以适应不同的参数类型或操作数类型。
1. 函数重载
函数重载是指在同一个作用域内定义多个同名函数,但它们的参数列表不同。
1.1 基本示例
cpp
#include <iostream>
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
std::string add(std::string a, std::string b) {
return a + b;
}
int main() {
std::cout << "10 + 20 = " << add(10, 20) << std::endl;
std::cout << "10.5 + 20.5 = " << add(10.5, 20.5) << std::endl;
std::cout << "Hello + World = " << add(std::string("Hello"), std::string("World")) << std::endl;
return 0;
}1.2 参数个数不同
cpp
#include <iostream>
int sum(int a) {
return a;
}
int sum(int a, int b) {
return a + b;
}
int sum(int a, int b, int c) {
return a + b + c;
}
int main() {
std::cout << "sum(10) = " << sum(10) << std::endl;
std::cout << "sum(10, 20) = " << sum(10, 20) << std::endl;
std::cout << "sum(10, 20, 30) = " << sum(10, 20, 30) << std::endl;
return 0;
}1.3 参数类型不同
cpp
#include <iostream>
void print(int num) {
std::cout << "整数: " << num << std::endl;
}
void print(double num) {
std::cout << "浮点数: " << num << std::endl;
}
void print(std::string str) {
std::cout << "字符串: " << str << std::endl;
}
int main() {
print(10);
print(10.5);
print("Hello");
return 0;
}2. 运算符重载
运算符重载是指为用户自定义的类型(类)重新定义运算符的行为。
2.1 重载算术运算符
cpp
#include <iostream>
class Complex {
private:
double real;
double imag;
public:
Complex(double real = 0, double imag = 0) : real(real), imag(imag) {}
Complex operator+(const Complex& other) {
return Complex(real + other.real, imag + other.imag);
}
Complex operator-(const Complex& other) {
return Complex(real - other.real, imag - other.imag);
}
Complex operator*(const Complex& other) {
return Complex(real * other.real - imag * other.imag,
real * other.imag + imag * other.real);
}
void print() {
std::cout << real << " + " << imag << "i" << std::endl;
}
};
int main() {
Complex c1(1.0, 2.0);
Complex c2(3.0, 4.0);
Complex c3 = c1 + c2;
Complex c4 = c1 - c2;
Complex c5 = c1 * c2;
std::cout << "c1 + c2 = ";
c3.print();
std::cout << "c1 - c2 = ";
c4.print();
std::cout << "c1 * c2 = ";
c5.print();
return 0;
}2.2 重载关系运算符
cpp
#include <iostream>
class Point {
private:
int x;
int y;
public:
Point(int x = 0, int y = 0) : x(x), y(y) {}
bool operator==(const Point& other) {
return x == other.x && y == other.y;
}
bool operator!=(const Point& other) {
return !(*this == other);
}
bool operator<(const Point& other) {
return x < other.x || (x == other.x && y < other.y);
}
void print() {
std::cout << "(" << x << ", " << y << ")" << std::endl;
}
};
int main() {
Point p1(1, 2);
Point p2(1, 2);
Point p3(3, 4);
std::cout << "p1 == p2: " << (p1 == p2) << std::endl;
std::cout << "p1 != p2: " << (p1 != p2) << std::endl;
std::cout << "p1 < p3: " << (p1 < p3) << std::endl;
return 0;
}2.3 重载输入输出运算符
cpp
#include <iostream>
class Point {
private:
int x;
int y;
public:
Point(int x = 0, int y = 0) : x(x), y(y) {}
friend std::ostream& operator<<(std::ostream& os, const Point& point);
friend std::istream& operator>>(std::istream& is, Point& point);
};
std::ostream& operator<<(std::ostream& os, const Point& point) {
os << "(" << point.x << ", " << point.y << ")";
return os;
}
std::istream& operator>>(std::istream& is, Point& point) {
is >> point.x >> point.y;
return is;
}
int main() {
Point point(10, 20);
std::cout << "point = " << point << std::endl;
std::cout << "请输入点的坐标(x y): ";
std::cin >> point;
std::cout << "point = " << point << std::endl;
return 0;
}2.4 重载赋值运算符
cpp
#include <iostream>
class String {
private:
char* data;
size_t size;
public:
String(const char* str = "") {
size = strlen(str);
data = new char[size + 1];
strcpy(data, str);
}
String(const String& other) {
size = other.size;
data = new char[size + 1];
strcpy(data, other.data);
}
String& operator=(const String& other) {
if (this != &other) {
delete[] data;
size = other.size;
data = new char[size + 1];
strcpy(data, other.data);
}
return *this;
}
~String() {
delete[] data;
}
void print() {
std::cout << data << std::endl;
}
};
int main() {
String str1("Hello");
String str2("World");
std::cout << "str1: ";
str1.print();
std::cout << "str2: ";
str2.print();
str1 = str2;
std::cout << "赋值后 str1: ";
str1.print();
return 0;
}2.5 重载下标运算符
cpp
#include <iostream>
class Array {
private:
int* data;
size_t size;
public:
Array(size_t size) : size(size) {
data = new int[size];
}
int& operator[](size_t index) {
return data[index];
}
const int& operator[](size_t index) const {
return data[index];
}
~Array() {
delete[] data;
}
};
int main() {
Array arr(5);
for (size_t i = 0; i < 5; i++) {
arr[i] = i * 10;
}
for (size_t i = 0; i < 5; i++) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
return 0;
}3. 运算符重载的规则
3.1 可以重载的运算符
以下运算符可以被重载:
- 算术运算符:
+、-、*、/、% - 关系运算符:
==、!=、<、>、<=、>= - 逻辑运算符:
&&、||、! - 位运算符:
&、|、^、~、<<、>> - 赋值运算符:
=、+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>= - 自增自减运算符:
++、-- - 下标运算符:
[] - 函数调用运算符:
() - 成员访问运算符:
-> - 逗号运算符:
, - 内存管理运算符:
new、delete、new[]、delete[]
3.2 不能重载的运算符
以下运算符不能被重载:
- 成员访问运算符:
. - 成员指针访问运算符:
.* - 作用域解析运算符:
:: - 条件运算符:
?: sizeof运算符typeid运算符
3.3 重载运算符的规则
- 不能创建新的运算符
- 不能改变运算符的优先级
- 不能改变运算符的操作数个数
- 至少有一个操作数是用户自定义的类型
- 重载运算符时,应该保持运算符的原始含义
4. 示例:综合运用
现在,让我们看一个综合运用各种重载特性的例子:
cpp
#include <iostream>
#include <cmath>
class Complex {
private:
double real;
double imag;
public:
Complex(double real = 0, double imag = 0) : real(real), imag(imag) {}
Complex operator+(const Complex& other) {
return Complex(real + other.real, imag + other.imag);
}
Complex operator-(const Complex& other) {
return Complex(real - other.real, imag - other.imag);
}
Complex operator*(const Complex& other) {
return Complex(real * other.real - imag * other.imag,
real * other.imag + imag * other.real);
}
Complex operator/(const Complex& other) {
double denominator = other.real * other.real + other.imag * other.imag;
return Complex((real * other.real + imag * other.imag) / denominator,
(imag * other.real - real * other.imag) / denominator);
}
bool operator==(const Complex& other) {
return real == other.real && imag == other.imag;
}
bool operator!=(const Complex& other) {
return !(*this == other);
}
double magnitude() {
return sqrt(real * real + imag * imag);
}
friend std::ostream& operator<<(std::ostream& os, const Complex& complex);
friend std::istream& operator>>(std::istream& is, Complex& complex);
};
std::ostream& operator<<(std::ostream& os, const Complex& complex) {
if (complex.imag >= 0) {
os << complex.real << " + " << complex.imag << "i";
} else {
os << complex.real << " - " << -complex.imag << "i";
}
return os;
}
std::istream& operator>>(std::istream& is, Complex& complex) {
is >> complex.real >> complex.imag;
return is;
}
int main() {
Complex c1(1.0, 2.0);
Complex c2(3.0, 4.0);
std::cout << "c1 = " << c1 << std::endl;
std::cout << "c2 = " << c2 << std::endl;
std::cout << std::endl;
Complex c3 = c1 + c2;
std::cout << "c1 + c2 = " << c3 << std::endl;
Complex c4 = c1 - c2;
std::cout << "c1 - c2 = " << c4 << std::endl;
Complex c5 = c1 * c2;
std::cout << "c1 * c2 = " << c5 << std::endl;
Complex c6 = c1 / c2;
std::cout << "c1 / c2 = " << c6 << std::endl;
std::cout << std::endl;
std::cout << "c1 == c2: " << (c1 == c2) << std::endl;
std::cout << "c1 != c2: " << (c1 != c2) << std::endl;
std::cout << std::endl;
std::cout << "|c1| = " << c1.magnitude() << std::endl;
std::cout << "|c2| = " << c2.magnitude() << std::endl;
std::cout << std::endl;
Complex c7;
std::cout << "请输入复数(实部 虚部): ";
std::cin >> c7;
std::cout << "你输入的复数是: " << c7 << std::endl;
return 0;
}小结
C++ 重载运算符和重载函数包括:
函数重载:
- 在同一个作用域内定义多个同名函数
- 参数列表不同(参数个数、参数类型、参数顺序)
运算符重载:
- 为用户自定义的类型重新定义运算符的行为
- 重载算术运算符:
+、-、*、/、% - 重载关系运算符:
==、!=、<、>、<=、>= - 重载输入输出运算符:
<<、>> - 重载赋值运算符:
= - 重载下标运算符:
[]
运算符重载的规则:
- 可以重载的运算符
- 不能重载的运算符
- 重载运算符的规则
关键概念:
- 函数重载:在同一个作用域内定义多个同名函数,但参数列表不同
- 运算符重载:为用户自定义的类型重新定义运算符的行为
- 友元函数:可以访问类的私有成员
- 成员函数:作为类的成员函数重载运算符
掌握重载是 C++ 面向对象编程的重要基础,在后续章节中,我们将学习 C++ 的多态。