【C++指南】运算符重载详解

news/2024/10/25 3:44:57/

引言

C++ 提供了运算符重载这一特性,允许程序员为自定义类型(如类和结构体)定义运算符的行为

通过运算符重载,可以使自定义类型对象像内置类型一样使用运算符,从而提高代码的可读性和易用性。

本文将详细介绍 C++ 中运算符重载的概念、语法、规则、注意事项以及实际应用。

 

目录

引言

 🍃运算符重载的概念

🍃运算符重载的语法

🍃可重载的运算符

🍃运算符重载的规则

🍃运算符重载的实现

🍃注意事项

🍃实际应用

示例代码

运算符重载的应用项目:日期类实现

结语


 🍃运算符重载的概念

运算符重载是指为类(或结构体)的特定运算符提供自定义实现,使其能够作用于类的对象。重载的运算符可以保持其原有的语义,也可以定义新的语义。

C++规 定类类型对象使⽤运算符时,必须转换成调⽤对应运算符重载,若没有对应的运算符重载,则会编译报错。

🍃运算符重载的语法

  • 运算符重载通过成员函数或友元函数来实现。
  • 运算符重载是具有特殊名字的函数,他的名字是由operator和后⾯要定义的运算符共同构成。
  • 和其他 函数⼀样,它也具有其返回类型和参数列表以及函数体。
  • 如果⼀个重载运算符函数是成员函数,则它的第⼀个运算对象默认传给隐式的this指针,因此运算 符重载作为成员函数时,参数比运算对象少⼀个 

  • 成员函数形式
class MyClass {  
public:  MyClass operator+(const MyClass& other) const; // 重载加法运算符  // ... 其他成员 ...  
};
  • 友元函数形式
class MyClass {  
public:  friend MyClass operator+(const MyClass& lhs, const MyClass& rhs); // 声明友元函数  // ... 其他成员 ...  
};  // 类外部定义友元函数  
MyClass operator+(const MyClass& lhs, const MyClass& rhs) {  // 实现加法运算  
}

🍃可重载的运算符

C++ 允许重载几乎所有的运算符,但有几个运算符不能重载:  .  .*    ::    ?:   sizeof 和 typeid。这些运算符与对象的成员访问、类型信息获取等底层操作紧密相关,因此不允许重载。

🍃运算符重载的规则

  • 不能改变运算符的优先级和结合性:重载的运算符仍然保持其原有的优先级和结合性。
  • 不能改变运算符的操作数个数:例如,不能将一元运算符重载为二元运算符,反之亦然。
  • 重载的运算符不能是新的类型:重载的运算符必须是 C++ 中已定义的运算符。
  • 成员运算符函数不能有默认参数:重载的运算符函数不能有默认参数。

🍃运算符重载的实现

  • 成员函数形式:当运算符重载为成员函数时,左侧操作数必须是该类的一个对象(或引用),而右侧操作数可以是任意类型(包括内置类型和该类类型)。
  • 友元函数形式:当运算符重载为友元函数时,两个操作数可以是任意类型(包括内置类型和该类类型),这提供了更大的灵活性。

🍃注意事项

  • 避免不必要的重载:只有当运算符的默认行为不适用于自定义类型时,才考虑重载。
  • 保持语义一致性:重载的运算符应尽可能保持其原有的语义,以避免混淆。
  • 注意异常安全性:在重载运算符时,要考虑到异常安全性,确保在异常发生时不会泄露资源或破坏对象状态。
  • 实用性:⼀个类需要重载哪些运算符,是看哪些运算符重载后有意义
  • 前置++与后置++:重载++运算符时,有前置++和后置++,运算符重载函数名都是operator++,无法很好的区分。 C++规定,后置++重载时,增加⼀个int形参,跟前置++构成函数重载,方便区分
  • 重载>>和<<:需要重载为全局函数,因为重载为成员函数,this指针默认抢占了第⼀个形参位 置,第⼀个形参位置是左侧运算对象,调⽤时就变成了对象<<cout,不符合语法和习惯。重载为全局函数把ostream/istream放到第⼀个形参位置就可以了,第⼆个形参位置当类类型对象

🍃实际应用

运算符重载在 C++ 中有着广泛的应用,例如:

  • 复数类:可以重载加法、减法、乘法和除法等运算符,使复数对象能够像内置类型一样进行算术运算。
  • 点类:可以重载加法运算符来表示点的平移,重载减法运算符来表示点的距离计算等。
  • 字符串类:可以重载加法运算符来表示字符串的连接,重载比较运算符来表示字符串的大小比较等。

示例代码

以下是一个简单的复数类示例,展示了如何重载加法、减法和乘法运算符:

#include <iostream>  class Complex {  
private:  double real;  double imag;  public:  // 构造函数  Complex(double r = 0, double i = 0) : real(r), imag(i) {}  // 重载加法运算符  Complex operator+(const Complex& other) const {  return Complex(real + other.real, imag + other.imag);  }  // 重载减法运算符  Complex operator-(const Complex& other) const {  return Complex(real - other.real, imag - other.imag);  }  // 重载乘法运算符  Complex operator*(const Complex& other) const {  return Complex(real * other.real - imag * other.imag, real * other.imag + imag * other.real);  }  // 重载输出运算符  friend std::ostream& operator<<(std::ostream& os, const Complex& c) {  os << c.real << " + " << c.imag << "i";  return os;  }  
};  int main() {  Complex c1(1, 2);  Complex c2(3, 4);  Complex c3 = c1 + c2;  Complex c4 = c1 - c2;  Complex c5 = c1 * c2;  std::cout << "c1: " << c1 << std::endl;  std::cout << "c2: " << c2 << std::endl;  std::cout << "c1 + c2: " << c3 << std::endl;  std::cout << "c1 - c2: " << c4 << std::endl;  std::cout << "c1 * c2: " << c5 << std::endl;  return 0;  
}

在这个示例中,我们定义了一个 Complex 类来表示复数,并重载了加法、减法和乘法运算符,以及输出运算符。这样,我们就可以像使用内置类型一样使用 Complex 对象进行算术运算和输出。

运算符重载的应用项目:日期类实现

详细内容参考文章,点击下方链接:

【C++指南】类和对象入门实践:日期类实现-CSDN博客

结语

运算符重载是 C++ 中的一个强大特性,它允许程序员为自定义类型定义运算符的行为。通过合理地使用运算符重载,可以使代码更加简洁、易读和高效。然而,在重载运算符时,需要遵循一定的规则和注意事项,以确保代码的正确性和安全性。

 


http://www.ppmy.cn/news/1541735.html

相关文章

光通信——前传基本架构

一、前传基本架构 第三代移动通信技术引入了分布式射频接入网络&#xff08;Distributed Radio Access Network &#xff0c; D-RAN&#xff09;架构。在此架构中的的基带处理单元&#xff08; Baseband Unit &#xff0c; BBU&#xff09; 和 射频拉远单元&#xff08; Remot…

王源携手匡威,官宣全球代言人身份,引全网热议

近日&#xff0c;匡威隆重宣布&#xff0c;青年偶像王源荣膺其全球品牌代言人。在官宣消息发布前夕&#xff0c;王源与匡威的合作便已在微博热搜上占据头榜&#xff0c;备受广大网友关注。 随着官宣及产品上线的钟声敲响&#xff0c;王源的粉丝们迅速行动起来&#xff0c;积极支…

【Linux】从 fork() 到 exec():理解 Linux 进程程序替换的魔法

1.前言 进程程序替换是指一个进程用另一个新的可执行程序来替换当前正在执行的程序&#xff0c;这个过程通过通过exec系列函数完成。在Linux或UNIX系统中&#xff0c;进程程序替换通常发生在一个进程通过fork()创建了子进程之后&#xff0c;子进程用exec()函数加载和执行另一个…

数据库表开发 vs 面向接口开发

时间&#xff1a;2024年 10月 24日 作者&#xff1a;小蒋聊技术 邮箱&#xff1a;wei_wei10163.com 微信&#xff1a;wei_wei10 音频地址&#xff1a;喜马拉雅 大家好&#xff0c;欢迎来到“小蒋聊技术”&#xff0c;我是小蒋&#xff01;今天我们来聊聊数据库表开发 vs 面…

SpringBoot基于若依项目工时统计成本核算管理源码带教程

是前后端分离的架构&#xff0c;前端使用Vue2&#xff0c;后端使用SpringBoot2。 技术框架&#xff1a;SpringBoot2.0.0 Mybatis1.3.2 Shiro swagger-ui jpa lombok Vue2 Mysql5.7 运行环境&#xff1a;jdk8 IntelliJ IDEA maven 宝塔面板 系统与功能介绍 这是一…

003 Qt_信号和槽-上

文章目录 前言信号与槽的概念信号的本质槽的本质信号与槽的连接自定义槽函数 小结 前言 本文将会向你介绍信号与槽的概念&#xff0c;以及如何自定义槽函数 信号与槽的概念 1、在 Qt 中&#xff0c;用户和控件的每次交互过程称为⼀个事件。 比如 “用户点击按钮” 是⼀个事件…

软件设计师备忘录

第1章 计算机系统知识 运算器&#xff1a;P2 算术逻辑单元(ALU)。U是运算器的重要组成部件&#xff0c;负责处理数据&#xff0c;实现对数据的算术运算和逻辑运算。 累加寄存器(AC)。算的结果是放在累加器中的&#xff0c;运算器中至少要有一个累加寄存器。 数据缓冲寄存器(DR…

media3 exoplayer 扩展解码库在这里 take it , please !

Media3 ExoPlayer 扩展解码库介绍 请注意&#xff0c;本文讨论的是 Media3 ExoPlayer 而不是 Google ExoPlayer2。详细参考&#xff1a;Media3 ExoPlayer 迁移指南 文章最后提供了已经编译好的AAR文件&#xff0c;直接引用即可&#xff01;&#xff01;&#xff01; 为什么选…