[C++]运算符重载

ops/2024/12/18 10:33:39/

一、 什么是运算符重载?

运算符重载是 C++ 中的一种功能,它允许用户定义的类或数据类型重新定义或扩展运算符的行为,使运算符能够作用于用户定义的对象。


二、 通俗解释

在 C++ 中,运算符(如 +, -, *, = 等)默认只能对内置类型(如 int, float)进行操作。
运算符重载允许用户通过特殊的函数定义,让运算符也能处理自定义类型(如类或结构体)。

例如:

  • 默认情况下,+ 只能用来加两个整数:3 + 5
  • 运算符重载后,+ 可以用来加两个对象(如 ComplexNumber 类对象)。

三、运算符重载的目的

  • 让自定义类型(如类和结构体)与内置类型一样,可以使用运算符进行运算或比较。
  • 使代码更简洁直观,提高程序的可读性和可维护性。

四、运算符重载的规则

  1. 不能重载的运算符:

    • ::(作用域运算符)
    • .*(成员指针运算符)
    • sizeof(计算对象大小)
    • typeid(类型识别运算符)
    • .(成员访问运算符)
  2. 运算符重载不会改变运算符的优先级和结合性

  3. 运算符重载不能引入新的运算符,只能重载已有的运算符。

  4. 不能改变运算符的操作数个数

    • 单目运算符:例如 -(负号)。
    • 双目运算符:例如 +, *, ==
  5. 运算符重载可以作为类的成员函数或友元函数,具体情况如下:

    • 成员函数:左操作数必须是当前类对象。
    • 友元函数:适用于左操作数不是当前类对象的情况。

五、重载运算符

运算符重载是通过特殊的函数实现的,这个函数名以 operator 开头,后面跟要重载的运算符。

1.运算符重载的实现方式

1.1 运算符重载作为类的成员函数

1.1.1语法格式:
ReturnType operator 运算符 (参数列表) {//ReturnType是运算符重载针对的数据类型// 重载运算符的逻辑
}
1.1.2 特点:
  • 左侧操作数必须是当前类的对象。(关于左操作数的解释下面会有具体的扩展哈)
  • 右侧操作数通过参数传递(如果是双目运算符)。
1.1.3 代码实例:重载 + 运算符(成员函数):计算两个复数的加法结果,并返回一个新的复数对象。(复数用对象表示,在对象的内部将复数的虚部和实部用成员变量来表示,即这里的一个Complex对象实例就是一个复数,这个对象里的real就是这个对象的实部,imag就是这个对象的虚部)
#include <iostream>
using namespace std;class Complex {int real, imag;public://构造一个结构体Complex(int r = 0, int i = 0) : real(r), imag(i) {}// 重载 + 运算符Complex operator+(const Complex& other) {return Complex(real + other.real, imag + other.imag);
//这里的other.real指的是其他的要跟当下的对象的real相加的实部(这里代码可以看做real是c1的虚部,other.real是c2的虚部)
//这里的other.imag指的是其他的要跟当下的对象的imag相加的实部(这里代码可以看做imag是c1的虚部,other.imag是c2的虚部)}void display() {cout << real << " + " << imag << "i" << endl;}
};int main() {Complex c1(3, 4), c2(1, 2);Complex c3 = c1 + c2;  // 调用重载的 + 运算符//创建了一个新的对象c3,利用Complex对象+重载运算符将c1,c2对象的虚部和实部对应的相加给c3(c1,c2的实部相加给c3的实部,c1,c2的虚部相加给c3的虚部)c3.display();return 0;
}
1.1.4 解释:
1.other 是什么?

在运算符重载函数中:

Complex operator+(const Complex& other) {return Complex(real + other.real, imag + other.imag);
}
  •  other 是重载 + 运算符函数的 参数
  • 它代表 + 运算符右侧的对象

例如:

Complex c1(3, 4), c2(1, 2);
Complex c3 = c1 + c2;

 在表达式 c1 + c2 中:

  • c1 是左操作数,它是调用 operator+ 的对象(this 指针隐式传递)。
  • c2 是右操作数,它作为参数 other 传递给 operator+ 函数。
2. other.realother.imag 是什么?

other 是一个 Complex 类型的对象,它具有 realimag 两个成员变量(实部和虚部)。

  • other.real:表示 other 对象的 实部
  • other.imag:表示 other 对象的 虚部
3.执行流程解析

1.创建对象 c1c2

Complex c1(3, 4);
Complex c2(1, 2);
  • c1real = 3, imag = 4

  • c2real = 1, imag = 2

2.调用 c1 + c2:

Complex c3 = c1 + c2;
  •  这行代码触发了 运算符重载函数 operator+
  • 在函数 operator+ 中:
    • this->realthis->imag 代表左操作数 c1 的实部和虚部。
    • other 是右操作数 c2
    • other.realother.imag 代表 c2 的实部和虚部。

3.具体计算过程:

return Complex(real + other.real, imag + other.imag);
  •  real + other.real3 + 1 = 4(计算新的实部)。
  • imag + other.imag4 + 2 = 6(计算新的虚部)。
  • 返回一个新的 Complex 对象,real = 4, imag = 6

4.输出结果:

  • 调用 display() 函数输出 c3 的值:
    4 + 6i
    

5.整个流程的梳理: 

6.在主函数部分:operator+ 函数是编译器自动调用的
  • 当你在代码中使用 + 运算符 作用于两个对象 时,编译器会自动去寻找并调用重载的 operator+ 函数。
  •  前提是你必须在类中提供 operator+ 函数的重载定义。
  • 出发operator的具体流程:(截图来自ChatGTP)

  • operator+ 函数的调用等价写法
    • 在表达式 c1 + c2 中,实际调用的是:
c1.operator+(c2);
  • 解释:
    • 左操作数调用 operator+,右操作数作为参数传入。计算相加结果,返回一个新对象。
    • c1 是调用 operator+ 函数的对象。
    • c2 是参数 other
    • 所以 c1 + c2 的行为与下面的代码等价:
Complex c3 = c1.operator+(c2);

 如果没有重载 + 运算符会发生什么?

如果你没有定义 operator+,编译器不知道如何处理两个 Complex 对象的 + 运算,程序会报错。如:

error: no match for ‘operator+’ (operand types are ‘Complex’ and ‘Complex’)
1.1.5补充:多个对象调用运算符重载: 
#include <iostream>
using namespace std;class Complex {int real, imag;public:Complex(int r = 0, int i = 0) : real(r), imag(i) {}// 重载 + 运算符Complex operator+(const Complex& other) {//括号内的参数表示指传入的参数是Complex型的数据并且传入参数是不可动的,是常对象,other表示这是运算符重载的右操作数return Complex(real + other.real, imag + other.imag);}void display() {cout << real << " + " << imag << "i" << endl;}
};int main() {Complex c1(3, 4), c2(1, 2), c3(2, 3);// 连续相加Complex c4 = c1 + c2 + c3;  // 触发两次 operator+,(c1+c2)触发一次operator,(c1+c2)的结果再加一次c3有触发一次operatorc4.display();  // 输出 6 + 9ireturn 0;
}
/*
输出:
6+9i
*/


1.2 运算符重载作为友元函数

语法格式:

friend ReturnType operator 运算符 (参数列表);
//如:
//friend Complex operator+(……)
//friend Complex operator-(……)
特点:
  • 左侧操作数可以是非当前类的对象。
  • 通常用于重载需要两个不同类型操作数的运算符(如输入输出运算符 <<>>)。

示例:重载 + 运算符(友元函数)

#include <iostream>
using namespace std;class Complex {int real, imag;public:Complex(int r = 0, int i = 0) : real(r), imag(i) {}// 友元函数重载 +friend Complex operator+(const Complex& c1, const Complex& c2);void display() {cout << real << " + " << imag << "i" << endl;}
};// 友元函数实现
//类外补充一下:友元函数的格式 函数返回类型 友元函数名(友元函数参数)
//这里的友元函数名必须要是(operator+),表示重载+运算符,这是C++的语法规定
Complex operator+(const Complex& c1, const Complex& c2) {return Complex(c1.real + c2.real, c1.imag + c2.imag);
}int main() {Complex c1(3, 4), c2(1, 2);Complex c3 = c1 + c2;  // 调用重载的 + 运算符c3.display();return 0;
}

2. 单目运算符的重载

单目运算符(如 -, ++, --)只需要一个操作数。

成员函数形式(单目运算符)

ReturnType operator 运算符 () {// 重载逻辑
}

代码实例:1.重载 - 运算符

#include <iostream>
using namespace std;class Complex {int real, imag;public:Complex(int r = 0, int i = 0) : real(r), imag(i) {}// 重载 - 运算符Complex operator-() {return Complex(-real, -imag);}void display() {cout << real << " + " << imag << "i" << endl;}
};int main() {Complex c1(-3, -4);   // 创建一个复数对象 c1,实部 = 3,虚部 = 4Complex c2 = -c1;   // 调用重载的 - 运算符cout << "Original Complex number: ";c1.display();cout << "Negated Complex number: ";c2.display();return 0;
}

2.代码示例:重载前置 ++-- 运算符

#include <iostream>
using namespace std;class Counter {int value;public:Counter(int v = 0) : value(v) {}// 重载前置 ++ 运算符Counter& operator++() {++value;  // 先增加return *this;  // 返回自身引用}// 重载前置 -- 运算符Counter& operator--() {--value;  // 先减少return *this;  // 返回自身引用}void display() const {cout << "Value: " << value << endl;}
};int main() {Counter c(10);++c;  // 调用前置 ++c.display();  // 输出 11--c;  // 调用前置 --c.display();  // 输出 10return 0;
}

3. 代码示例:重载后置 ++-- 运算符(后置 ++-- 需要一个 int 参数 作为区分标志。)

#include <iostream>
using namespace std;class Counter {int value;public:Counter(int v = 0) : value(v) {}// 重载后置 ++ 运算符Counter operator++(int) {//后置 ++ 和 -- 需要一个 int 参数 作为区分标志。Counter temp = *this;  // 保存当前值value++;  // 增加return temp;  // 返回之前的值}// 重载后置 -- 运算符Counter operator--(int) {//后置 ++ 和 -- 需要一个 int 参数 作为区分标志。Counter temp = *this;  // 保存当前值value--;  // 减少return temp;  // 返回之前的值}void display() const {cout << "Value: " << value << endl;}
};int main() {Counter c(10);c++;  // 调用后置 ++c.display();  // 输出 11c--;  // 调用后置 --c.display();  // 输出 10return 0;
}

 


3. 双目运算符的重载

双目运算符(如 +, -, *, ==)需要两个操作数。

成员函数形式(双目运算符)

ReturnType operator 运算符 (const Type& other) {// 重载逻辑
}

 

2.1 重载 + 运算符

代码示例:重载 + 运算符

#include <iostream>
using namespace std;class Complex {int real, imag;public:Complex(int r = 0, int i = 0) : real(r), imag(i) {}// 重载 + 运算符Complex operator+(const Complex& other) const {return Complex(real + other.real, imag + other.imag);}void display() const {cout << real << " + " << imag << "i" << endl;}
};int main() {Complex c1(3, 4), c2(1, 2);Complex c3 = c1 + c2;  // 使用重载的 + 运算符c3.display();  // 输出 4 + 6ireturn 0;
}

2.2 重载 - 运算符

代码示例:重载 - 运算符

#include <iostream>
using namespace std;class Complex {int real, imag;public:Complex(int r = 0, int i = 0) : real(r), imag(i) {}// 重载 - 运算符Complex operator-(const Complex& other) const {return Complex(real - other.real, imag - other.imag);}void display() const {cout << real << " + " << imag << "i" << endl;}
};int main() {Complex c1(5, 7), c2(2, 3);Complex c3 = c1 - c2;  // 使用重载的 - 运算符c3.display();  // 输出 3 + 4ireturn 0;
}

2.3 重载 * 运算符

代码示例:重载 * 运算符

#include <iostream>
using namespace std;class Multiply {int value;public://构造函数传参Multiply(int v = 1) : value(v) {}// 重载 * 运算符Multiply operator*(const Multiply& other) const {return Multiply(value * other.value);}void display() const {cout << "Value: " << value << endl;}
};int main() {Multiply m1(5), m2(6);Multiply m3 = m1 * m2;  // 使用重载的 * 运算符m3.display();  // 输出 Value: 30return 0;
}

2.4 重载 == 运算符

代码示例:重载 == 运算符

#include <iostream>
using namespace std;class Complex {int real, imag;public:Complex(int r = 0, int i = 0) : real(r), imag(i) {}// 重载 == 运算符,即判断两个复数是否相等bool operator==(const Complex& other) const {return (real == other.real) && (imag == other.imag);//实部和虚部相同时这两个复数相同}void display() const {cout << real << " + " << imag << "i" << endl;}
};int main() {Complex c1(3, 4), c2(3, 4), c3(1, 2);if (c1 == c2) {//这里因为是两个复数对象在比较是否相等,故在这里会自动调用==重载cout << "c1 and c2 are equal" << endl;} else {cout << "c1 and c2 are not equal" << endl;}if (c1 == c3) {//同上cout << "c1 and c3 are equal" << endl;} else {cout << "c1 and c3 are not equal" << endl;}return 0;
}

4. 流插入运算符 << 和流提取运算符 >> 的重载

这两个运算符通常需要将 左操作数 定义为 ostreamistream,因此它们必须通过 友元函数 实现

语法格式:

friend ostream& operator<<(ostream& out, const Type& obj);
friend istream& operator>>(istream& in, Type& obj);

代码实例:重载 <<>> 运算符

#include <iostream>
using namespace std;class Complex {int real, imag;public:Complex(int r = 0, int i = 0) : real(r), imag(i) {}// 重载 << 运算符friend ostream& operator<<(ostream& out, const Complex& c) {out << c.real << " + " << c.imag << "i";//输出一个完整的复数return out;}// 重载 >> 运算符friend istream& operator>>(istream& in, Complex& c) {cout << "输入负数的实数部分和虚数部分: ";in >> c.real >> c.imag;//输入虚数的实部和虚部return in;}
};int main() {Complex c1;cin >> c1;          // 输入重载,用于将只能输入实部和虚部的功能转化为能输入一个完整的复数输出cout << "Result: " << c1 << endl;  // 输出重载return 0;
}

关于in和out:

1.out和in是什么?

outin 其实是 大类的概念,它们属于 C++ 标准库中定义的 输入输出流体系,包含了很多 具体的输入/输出流对象

  • out:输出流对象(如 cout),用于输出数据到屏幕。
  • in:输入流对象(如 cin),用于从键盘读取输入数据。

 

2.out:输出流对象

这一行代码:

out << c.real << " + " << c.imag << "i";
  • out 是输出流对象,比如 cout(这是一个标准输出流/屏幕输出)
  • << 运算符c.real" + "c.imag 拼接成一串数据,送到输出流 out,然后显示到屏幕上。
  • 所以,这里是在将 c.realc.imag 的值以 "real + imagi" 的格式输出到屏幕。

3.in:输入流对象

这一行代码:

in >> c.real >> c.imag;
  • in 是输入流对象,比如 cin(这是一个标准输入流/键盘输入)
  • >> 运算符 从键盘输入流中读取用户输入的数据,然后赋值给 c.realc.imag
  • 这里的 c.realc.imag 属于参数 c 对象的成员变量。


5. 类型转换运算符重载

类型转换运算符重载允许自定义类的对象能够隐式或显式地转换为其他指定的类型,比如可以让自定义类对象转换为基本数据类型(如 intdouble 等),或者转换为其他用户自定义类型。这样做的好处是能够使自定义类更好地融入到 C++ 语言已有的类型体系中,方便在各种需要相应类型值的场景中使用类对象。

5.1语法格式:

operator 目标类型() const {// 转换的具体实现逻辑,返回目标类型的值return 具体要返回的值;//必须返回转换后的值
}
  • operator:表示重载的类型转换运算符。
  • 目标类型:要转换成的目标数据类型(例如 intfloat 等)。
  • const(可选):表示该函数不会修改类的成员变量。
  • 返回值:必须返回转换后的值。

5.2 特点

  1. 没有参数:类型转换运算符重载函数不能有参数。
  2. 不能指定返回类型:返回类型必须是转换目标的类型(即类型名)。
    class ErrorExample {
    public:int operator double() const {// 错误写法,不能写返回类型 intreturn 0;}
    };
  3. 可以重载多个不同类型:可以为一个类重载多个类型转换运算符。
  4. 隐式调用:类型转换运算符重载可以在需要时自动调用。

5.3 应用场景

  • 类对象 转换为 基本数据类型(如 intfloat)。
  • 类对象 转换为 另一个类的对象

C++ 运算符重载 中,强制类型转换运算符重载 是一个比较特殊的知识点。下面我会详细讲解关于强制类型转换的相关知识点,包括定义、语法、特点、应用场景和代码示例。


5.4 代码示例

示例 1:将类对象转换为 int 类型
#include <iostream>
using namespace std;class Complex {int real, imag;public:Complex(int r = 0, int i = 0) : real(r), imag(i) {}// 重载类型转换运算符,将 Complex 转换为 intoperator int() const {return real;  // 返回实部,作为转换后的值}void display() const {cout << real << " + " << imag << "i" << endl;}
};int main() {Complex c1(3, 4);// 将 c1 转换为 int 类型int intValue = c1;cout << "Complex object: ";c1.display();cout << "Converted to int: " << intValue << endl;return 0;
}
输出结果:
Complex object: 3 + 4i Converted to int: 3
解释
  • 通过重载 operator int(),当我们写 int intValue = c1; 时,编译器自动调用重载的类型转换函数。
  • 返回值为 c1 的实部 real,因此 intValue 变成了 3

示例 2:将类对象转换为 float 类型
#include <iostream>
using namespace std;class Distance {float meters;public:Distance(float m = 0) : meters(m) {}// 重载类型转换运算符,将 Distance 转换为 floatoperator float() const {return meters;  // 返回距离值}void display() const {cout << meters << " meters" << endl;}
};int main() {Distance d(5.75);// 将 d 转换为 float 类型float distanceValue = d;cout << "Distance object: ";d.display();cout << "Converted to float: " << distanceValue << endl;return 0;
}
输出结果
Distance object: 5.75 meters Converted to float: 5.75
解释
  • 重载 operator float(),实现 Distance 类到 float 类型的转换。
  • 当写 float distanceValue = d; 时,编译器自动调用该函数,返回 meters 的值。

示例 3:将类对象转换为另一个类对象
#include <iostream>
using namespace std;class Fahrenheit;class Celsius {float temperature;public:Celsius(float temp = 0) : temperature(temp) {}// 类型转换运算符:将 Celsius 转换为 Fahrenheitoperator Fahrenheit();void display() const {cout << "Celsius: " << temperature << "°C" << endl;}
};class Fahrenheit {float temperature;public:Fahrenheit(float temp = 0) : temperature(temp) {}void display() const {cout << "Fahrenheit: " << temperature << "°F" << endl;}friend class Celsius;  // 声明 Celsius 为友元类
};// 定义 Celsius 到 Fahrenheit 的类型转换
Celsius::operator Fahrenheit() {return Fahrenheit(temperature * 9 / 5 + 32);  // 摄氏度转华氏度
}int main() {Celsius c(25);  // 25°CFahrenheit f = c;  // 自动调用类型转换运算符c.display();f.display();return 0;
}
输出结果
Celsius: 25°C Fahrenheit: 77°F
解释
  • Celsius 类重载了类型转换运算符,将 Celsius 对象转换为 Fahrenheit 对象。
  • 当写 Fahrenheit f = c; 时,自动调用重载的 operator Fahrenheit(),进行摄氏度到华氏度的转换。
示例4:将自定义类对象转换为另一个自定义类类型(假设存在 Point 和 Vector 类,将 Vector 转换为 Point
#include <iostream>
using namespace std;// 点类,二维坐标表示
class Point {
private:int x;int y;public:Point(int a = 0, int b = 0) : x(a), y(b) {}void display() {cout << "(" << x << ", " << y << ")" << endl;}
};// 向量类
class Vector {
private:int dx;int dy;public:Vector(int a = 0, int b = 0) : dx(a), dy(b) {}// 重载类型转换运算符,使 Vector 类能转换为 Point 类operator Point() const {return Point(dx, dy);}
};int main() {Vector vec(3, 4);// 隐式调用类型转换运算符,将 Vector 类对象转换为 Point 类对象Point p = vec;  p.display();return 0;
}
  • 分别定义了 Point 类用于表示二维平面上的点,有 x 和 y 坐标成员变量;以及 Vector 类表示二维向量,有 dx 和 dy 成员变量。
  • 通过在 Vector 类中重载 operator Point() 类型转换运算符,定义了将 Vector 类对象转换为 Point 类对象的规则,即使用 Vector 的 dx 和 dy 分量来构造一个 Point 对象。
  • 在 main 函数中,当把 Vector 类对象赋值给 Point 类对象时,就会自动调用重载的转换运算符完成转换。
示例5:将自定义类对象转换为指针类型(以转换为 char* 类型指针为例,模拟一个简单的字符串类转换)
#include <iostream>
#include <cstring>
using namespace std;// 简单的自定义字符串类
class MyString {
private:char* data;int len;public:MyString(const char* str = "") {len = strlen(str);data = new char[len + 1];strcpy(data, str);}~MyString() {delete[] data;}// 重载类型转换运算符,使其能转换为 char* 类型指针operator char*() const {return data;}
};int main() {MyString myStr("Hello, World!");// 隐式调用类型转换运算符,将 MyString 类对象转换为 char* 类型指针char* ptr = myStr;  cout << ptr << endl;return 0;
}
  • 定义了 MyString 类,内部通过动态分配内存来存储字符串内容,有成员变量 data(指向存储字符串的字符数组)和 len(记录字符串长度)。
  • 通过重载 operator char*() 类型转换运算符,使得 MyString 类对象可以转换为 char* 类型的指针,返回其内部存储字符串的指针 data
  • 在 main 函数里,将 MyString 类对象赋值给 char* 类型指针变量时,编译器会自动调用重载的转换运算符来进行转换,之后就能像使用普通 char* 类型字符串指针一样操作它(比如输出字符串内容)。

6.扩:左操作数

6.1关于左操作数的通俗解释左操作数 是指在运算符表达式中,运算符左侧的那个操作数。

举个简单的例子:

a + b;

在这个表达式中,运算符 + 左边的 a 就是 左操作数,右边的 b 就是 右操作数

对于运算符 +

  • 左操作数a
  • 右操作数b

6.2 运算符重载中的左操作数

  • 类成员函数 重载运算符时,左操作数必须是当前类的对象,因为成员函数是由对象调用的。
  • 友元函数 重载运算符时,左操作数可以是任意类型(类对象或其他类型),因为友元函数不属于类,可以自由指定操作数。

6.3 代码实例:成员函数与友元函数的左操作数

6.3.1 类成员函数中的左操作数

在类成员函数中重载运算符时,左操作数是调用运算符的对象(当前对象 this):

#include <iostream>
using namespace std;class Complex {int real, imag;public:Complex(int r = 0, int i = 0) : real(r), imag(i) {}// 成员函数重载 +Complex operator+(const Complex& other) {cout << "Left operand: " << real << " + " << imag << "i" << endl;return Complex(real + other.real, imag + other.imag);}void display() {cout << real << " + " << imag << "i" << endl;}
};int main() {Complex c1(1, 2), c2(3, 4);Complex c3 = c1 + c2;  // c1 是左操作数,c2 是右操作数c3.display();return 0;
}

输出:

Left operand: 1 + 2i 4 + 6i

解释:

  • 表达式 c1 + c2 中,c1左操作数,会调用成员函数 operator+
  • other 参数是 右操作数,即 c2

6.3.2 友元函数中的左操作数

在友元函数中,左右操作数都作为参数传递,因此 左操作数可以是非类对象

#include <iostream>
using namespace std;class Complex {int real, imag;public:Complex(int r = 0, int i = 0) : real(r), imag(i) {}// 友元函数重载 +friend Complex operator+(const Complex& c1, const Complex& c2) {cout << "Left operand: " << c1.real << " + " << c1.imag << "i" << endl;return Complex(c1.real + c2.real, c1.imag + c2.imag);}void display() {cout << real << " + " << imag << "i" << endl;}
};int main() {Complex c1(1, 2), c2(3, 4);Complex c3 = c1 + c2;  // 左操作数是 c1,右操作数是 c2c3.display();return 0;
}

输出:

Left operand: 1 + 2i 4 + 6i

解释:

  • 表达式 c1 + c2 中,c1 是左操作数,c2 是右操作数。
  • 在友元函数中,左右操作数通过参数列表传入,不需要依赖 this 指针。

6.4 左操作数与运算符重载的联系

类成员函数:
  • 左操作数是调用运算符的对象(通过 this 指针隐式传入)。
  • 示例c1 + c2 → 左操作数是 c1,调用 c1.operator+()
友元函数:
  • 左操作数和右操作数都通过参数列表传递。
  • 示例c1 + c2 → 左操作数是 c1,友元函数参数为 (c1, c2)

6.5 为什么左操作数对运算符重载很重要?

  • 类成员函数 的运算符重载要求左操作数是当前类的对象。
  • 友元函数 则没有这样的限制,提供了更大的灵活性,适用于左操作数不是类对象的情况。

六、运算符重载的总结

运算符类型重载形式使用场景
单目运算符成员函数负号 -, 递增 ++
双目运算符成员或友元函数+, 比较 ==, 赋值 =
输入输出运算符友元函数流插入 <<, 流提取 >>
类型转换运算符成员函数类对象与内置类型间的转换

七、 关键点归纳

  1. 成员函数友元函数 是运算符重载的两种实现方式。
    • 成员函数:左侧操作数必须是当前类对象。
    • 友元函数:适用于左右操作数不同的情况。
  2. 流插入运算符 << 和流提取运算符 >> 必须用友元函数重载。
  3. 单目和双目运算符 的重载遵循语法规范,不能改变操作数的数量。
  4. 类型转换运算符 通过 operator type() 重载实现对象与内置类型的转换。

http://www.ppmy.cn/ops/142883.html

相关文章

电气CAD制图软件概述及主要电气CAD软件介绍

一、电气CAD制图软件概述 电气CAD制图软件&#xff0c;即电气计算机辅助设计软件&#xff0c;是一种用于电气系统设计的专业软件。这类软件能够通过计算机帮助电气工程师完成从简单的电路设计到复杂的电气系统设计等各种任务。常用的电气CAD制图软件主要有AutoCAD, EPLAN,SEE E…

Java Math、System、Runtime

1. Math (1) 代表数学&#xff0c;是一个工具类&#xff0c;里面提供的都是对数据操作的一些静态方法。 (2) Math 类常见的方法&#xff1a; 方法说明public static int abs(int a)获取参数的绝对值(其他基本类型方法相同)public static double ceil(double a)向上取整public …

️Java如何根据前端返回的字段名进行动态数据查询?——深入探究与实战演练

全文目录&#xff1a; 开篇语前言&#x1f4dc;目录&#x1f304; 前言&#x1f9d0; 场景分析&#xff1a;为什么要根据字段名查询&#xff1f;&#x1f4a1; 设计思路&#xff1a;如何实现动态查询&#xff1f;1. 动态构造查询条件2. 使用映射数据结构存储字段条件3. 考虑使用…

6.3.1 MR实战:计算总分与平均分

在本次实战中&#xff0c;我们的目标是利用Apache Hadoop的MapReduce框架来处理和分析学生成绩数据。具体来说&#xff0c;我们将计算一个包含五名学生五门科目成绩的数据集的总分和平均分。这个过程包括在云主机上准备数据&#xff0c;将成绩数据存储为文本文件&#xff0c;并…

三维测量与建模笔记 - 7.2 点云滤波

逐点计算法向量&#xff0c;需要对每一个点拟合出它的切平面&#xff0c;一般使用邻域点信息来查找切平面。 选取要计算的点和它周围一定范围内的点可以拟合出一个平面&#xff0c;最基本的方法是通过最小二乘法取对这些点到平面的距离进行优化&#xff08;计算量很大&#xff…

Java集合类 HashMap 深度解读(含源码解析)

目录 HashMap基本概念 什么是HashMap HashMap的特点 HashMap类的继承和实现关系 深入了解HashMap前需要知道 hashCode()和equals()方法的关系 重写hashCode()方法的基本规则 HashMap的底层数据结构 JDK 1.8后采用数组 链表 红黑树 负载因子与扩容机制 为什么默认负…

【算法day16】二叉树:搜索二叉树的修剪与构建

题目引用 修剪二叉搜索树将有序数组转换为二叉搜索树把二叉搜索树转换为累加树 1. 修剪二叉搜索树 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在…

如何使用 Python 读取和写入 CSV 文件?

在Python中&#xff0c;处理CSV文件是一项常见的任务&#xff0c;通常用于数据交换和数据存储。 Python的标准库csv模块提供了一种方便的方式来读取和写入CSV文件。 下面我将详细介绍如何使用Python的csv模块来读取和写入CSV文件&#xff0c;并提供一些实际开发中的建议和注意…