C++ | 运算符重载

news2024/11/18 3:34:57

目录

概念

写法

约定俗成

注意事项


概念

其实早在刚开始学习C++的时候我们就已经接触到运算符重载了,只是我们当时还没意识到。

std::cout << "Hello World" << std::endl;

对于这一句代码的解释如下:

cout其实是一个iostream类的对象,它重载了左移运算符(operator<< ),每次调用的时候就会向输出设备(一般就是控制台)输出东西。也就是说<<原本是一个左移运算符,但通过所谓的“重载操作”之后就可以执行输出操作了。

而至于运算符重载是什么呢?

        运算符重载是一种C++编程特性,它允许程序员重新定义已有的运算符的行为,使得自定义的数据类型(类)可以像内置类型一样使用这些运算符。通过运算符重载,可以让自定义类对象之间进行各种运算和操作,使代码更加直观、灵活和易于理解。

        在C++中,运算符重载通过重载函数(也称为运算符函数)来实现,这些函数的名称和运算符相同,但在函数名前加上"operator"关键字,后面紧跟着运算符的符号。运算符重载函数可以定义为类的成员函数或全局函数,取决于运算符重载的需求和设计。

写法

接下来就让我们继续探讨C++运算符重载的写法。写法就是将函数设置为如下格式:

返回值 operator运算符( 参数… );

下面是代码示例模板:

class MyClass {
public:
    // 构造函数(如果需要)
    MyClass(/* 参数列表 */)
    {
        // 在这里初始化对象的成员变量
    }

    // 一元运算符重载
    // 例如:一元取反运算符(-),一元递增运算符(++)
    // 返回类型 operator运算符() {
    //     在这里定义运算符的操作
    // }

    // 二元运算符重载
    // 例如:二元加法运算符(+),二元乘法运算符(*)
    // 返回类型 operator运算符(const MyClass& other) {
    //     在这里定义运算符的操作
    // }

    // 赋值运算符重载
    // 返回类型 operator=(const MyClass& other) {
    //     在这里定义运算符的操作
    // }

    // 其他常见运算符重载
    // 例如:等于运算符(==),不等于运算符(!=),小于运算符(<),大于运算符(>)
    // 返回类型 operator运算符(const MyClass& other) {
    //     在这里定义运算符的操作
    // }

    // 友元函数(如果需要)
    // 例如:输出运算符(<<),输入运算符(>>)
    // friend 返回类型 operator运算符(std::ostream& os, const MyClass& obj) {
    //     在这里定义运算符的操作
    //     return os;
    // }
};

// 请注意,如果运算符是成员函数,它至少有一个操作数(隐含的 this 指针),
// 而如果运算符是全局函数(通过友元实现),它也许会有两个操作数。

// 如果运算符重载作为成员函数,使用对象的方式调用:
// MyClass obj1, obj2, result;
// result = obj1.operator+(obj2);  // 调用二元加法运算符重载

// 如果运算符重载作为全局函数(通过友元实现),使用函数的方式调用:
// MyClass obj1, obj2, result;
// result = operator+(obj1, obj2); // 调用二元加法运算符重载

如果不知道哪些运算符可以重载,哪些运算符不能重载,以及对于一个陌生的运算符重载函数该如何书写还感到疑惑,可以尝试看这篇博客:C++中一些常见的运算符重载代码模板

约定俗成

在C++中,一般来说,大多数运算符的重载既可以在类内声明,也可以在类外声明。然而,有一些约定俗成的实践和限制,决定了哪些运算符更适合在类内重载,哪些更适合在类外重载,以及哪些运算符在类内外重载无所谓。大致内容见下图:

 具体细节如下:

类内重载

  1. 单目运算符:单目运算符只涉及一个操作数,比如自增(++)和自减(--)运算符。这类运算符通常可以在类内进行重载,因为它们的操作数是对象本身。
  2. 赋值运算符:赋值运算符通常在类内进行重载,用于对类的成员变量进行赋值操作。这样可以很方便地访问类的私有成员。
  3. 下标运算符:下标运算符用于对象进行类似于数组的访问,通常也在类内重载。
  4.  函数调用运算符:函数调用运算符(就是一对小括号)一般也在类内重载,用于使类的对象可以像函数一样被调用。

类外重载

  1. 双目运算符:双目运算符涉及两个操作数的运算,例如加法(+)、减法(-)和乘法(*)等。对于双目运算符,尤其是涉及非成员类型的运算符,更倾向于在类外重载。这样可以保持对称性,允许两个不同类型的对象之间进行运算。
  2. 流插入和流提取:流插入运算符(<<)和流提取运算符(>>)通常在类外部进行重载。这样使得能够以自定义的方式进行输入和输出操作,而不需要改变类的定义。
  3. 关系运算符:关系运算符(如<、>、<=、>=、==、!=)通常在类外部重载,特别是涉及两个不同类对象之间的比较。

类内类外无所谓

算术运算符:加法、减法、乘法、除法等算术运算符既可以在类内重载,也可以在类外重载,这取决于对类的设计和需求。如果运算符只涉及一个操作数(一元运算符),通常在类内重载。如果涉及两个操作数(二元运算符),则可以在类内或类外重载。

注意事项

下面是使用C++运算符重载时的一些注意事项:

  1. C++中不允许用户定义新的运算符,只能对已有的运算符进行重载。
  2. 重载后的运算符的优先级、结合性也要保持不变,也不能改变其操作数及语法结构。
  3. 重载后的含义与原运算符的含义要保持一致。例如+重载之后也应为加的含义。
  4. 运算符重载函数不能有默认参数,否则就意味着改变了运算符操作数的个数。
  5. 运算符重载既可以在类内定义,也可以在类外全局下定义。 
  6. 运算符重载函数至少要有一个自定义类型的参数,因为如果都是内置类型的话,运算符重载也就没有意义了。
  7. 当运算符重载函数在类内声明时,其形参看起来比操作数数目少1,这是因为函数的第一个参数为隐式的this指针。
  8. 建议不要重载operator&& 和 operatorll。原因是无法在这两种情况下实现内置操作符的完整语义。说得更具体一些,内置版本版本特殊之处在于:内置版本的 && 和 II 有很灵活的短路规则,而我们自定义的运算符重载无法实现 && 和 || 的短路规则,与长久以来的习惯冲突,所以最好不要重载 && 和 ||。
  9. 点运算符(.)、域运算符(::)、点星运算符 (.*)、条件运算符( ? : )以及sizeof运算符,这5个运算符不能发生重载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/800029.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

虚拟机 RHEL8 安装 MySQL 8.0.34

目录 安装步骤一、清除所有残留的旧MySQL二、安装MySQL 报错问题1. 提示未找到匹配的参数&#xff1a; mysql-community-server2. 公钥问题 安装步骤 一、清除所有残留的旧MySQL 1. 关闭MySQL [rootlocalhost /]# service mysqld stop Redirecting to /bin/systemctl stop …

pyspark 笔记 pyspark.sql.function col VS select

0 原始数据 假如我们有这样的一个数据 1 功能上相似 都类似于python的DataFrame中的 df[col_id]&#xff0c;对列取切片的操作 2 区别 使用col之后&#xff0c;可以进行计算&#xff1b;而原版select 则无法进行计算

微服务模式:业务服务模式

无论是单体应用还是微服务&#xff0c;构建企业应用的业务逻辑/服务在更多方面上都有相似之处而不是差异。在两种方法中&#xff0c;都包含服务、实体、仓库等类。然而&#xff0c;也会发现一些明显的区别。在本文中&#xff0c;我将试图以概念性的方式强调这些区别&#xff0c…

Vue2基础二、常用指令

零、文章目录 Vue2基础二、常用指令 1、Vue指令是什么 概念&#xff1a;指令&#xff08;Directives&#xff09;是 Vue 提供的带有 v- 前缀 的 特殊 标签属性。Vue 会根据不同的【指令】&#xff0c;针对标签实现不同的【功能】。**为啥要学&#xff1a;**提高程序员操作 D…

SpringBoot 和 Vue 参数类型不对应,导致method parameter is not present

org.springframework.web.bind.MissingServletRequestParameterException: Required request parameter id for method parameter type String is not present 客户端&#xff1a; requestUserInfoById()const requestUserInfoById async (id?: string) > {} 服务器端&am…

【C++】C++11——包装器

文章目录 1. function包装器1.1 遇到的问题1.2 包装器的定义1.3 解决问题1.4 包装器的其他应用 2. bind2.1 bind的定义2.2 bind包装器绑定固定参数2.3 bind包装器调整传参顺序2.4 bind包装器的意义 1. function包装器 1.1 遇到的问题 我们首先来看一行代码&#xff1a; ret …

Kafka 入门到起飞系列 - 消费者组管理、位移管理

消费者组 - Consumer Group 上文我们已经讲过消费者组了&#xff0c;我们知道消费组的存在可以保证一个主题下一个分区的消息只会被组内一个消费者消费&#xff0c;从而避免了消息的重复消费 什么是消费组 - Consumer Group&#xff1f; 消费者组是Kafka 提供的可扩展且具有容…

Vue教程(二):数据代理和事件处理

1、数据代理 数据代理 通过obj2操作obj1的对象 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport"…

【图论】三种中心性 —— 特征向量、katz 和 PageRank

维基百科&#xff1a;在图论和网络分析中&#xff0c;中心性指标为图中相应网络位置的节点分配排名或数值。中心性这一概念最初起源于社交网络分析&#xff0c;因此很多衡量中心性的术语也反映了其社会学背景。 不同中心性指标对 “重要” 的衡量方式不同&#xff0c;因此适用于…

Android调用摄像头拍照从相册中选择图片

以下内容摘自郭霖《第一行代码》第三版 activity_main.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.android.com/apk/res-a…

简单分享婚宴预订小程序怎么做

婚宴预订小程序需要具备一些功能&#xff0c;通过这些功能&#xff0c;新人可以更方便地选择婚宴场地、预订服务&#xff0c;并且更好地规划自己的婚礼。 1. 场地浏览与选择 婚宴预订小程序可以展示多个婚宴场地的照片和详细信息&#xff0c;包括容纳人数、场地设施、价格等。…

Flutter:flutter_local_notifications——消息推送的学习

前言 注&#xff1a; 刚开始学习&#xff0c;如果某些案例使用时遇到问题&#xff0c;可以自行百度、查看官方案例、官方github。 简介 Flutter Local Notifications是一个用于在Flutter应用程序中显示本地通知的插件。它提供了一个简单而强大的方法来在设备上发送通知&#…

PHP 3des加解密新旧方法可对接加密

一、旧3des加解密方法 <?php class Encrypt_3DES {//加密秘钥&#xff0c;private $_key;private $_iv;public function __construct($key, $iv){$this->_key $key;$this->_iv $iv;}/*** 对字符串进行3DES加密* param string 要加密的字符串* return mixed 加密成…

blender 用蒙版添加材质

一、添加材质常规方法 选择物体新建材质&#xff0c;shift a 新建图像纹理&#xff0c;此时会发现添加上的纹理会有接缝&#xff0c;shift a 新建映射 纹理坐标&#xff0c;纹理坐标选择生成&#xff0c;此时&#xff0c;之前的接缝便会消失&#xff1b; 如何快捷添加纹理坐…

【应用】Asible自动化运维工具的应用与常用命令

ansible自动化运维工具 一、ansible 的概述1. ansible 的概念2. ansible 的特性 二、ansible 的部署与命令1. ansible 的部署1.1 服务器ip地址设置1.2 ansible 服务器部署 2. ansible 命令行模块2.1 command 模块2.2 shell 模块2.3 cron 模块2.4 user 模块2.5 group 模块2.6 co…

TCP KeepAlive与HTTP Keep-Alive

TCP KeepAlive与HTTP Keep-Alive TCP KeepAliveHTTP Keep-AliveTCP服务器怎么检测客户端断开连接 TCP KeepAlive TCP连接建立之后&#xff0c;如果应用程序或者上层协议一直不发送数据&#xff0c;或者隔很长时间才发送一次数据&#xff0c;那么TCP需要判断是应用程序掉线了还…

postgresql|数据库|启动数据库时报错:FATAL: could not map anonymous shared memory的解决

前言&#xff1a; 一个很偶然的出现的问题&#xff0c;因为我需要验证备份文件是否正确&#xff0c;因此&#xff0c;我在一台已启动了一个数据库实例的服务器上&#xff0c;依据全备的数据库文件在启动一个实例&#xff0c;当然&#xff0c;在此之前&#xff0c;已经修改了备…

C语言习题练习

C语言习题练习 一、offsetof宏二、交换奇偶位三、原地移除数组总结 一、offsetof宏 首先我们要了解什么是offsetof宏&#xff1a; . 此具有函数形式的宏返回数据结构或联合类型中成员成员的偏移值&#xff08;以字节为单位&#xff09;。 . 返回的值是size_t类型的无符号整数…

DevOps(四)

CD(二) 1. CDStep 1 - 上传代码Step 2 - 下载代码Step 3 - 检查代码Step 4 - 编译代码Step 5 - 上传仓库Step 6 - 下载软件Step 7 - 制作镜像Step 8 - 上传镜像Step 9 - 部署服务2. 整体预览2.1 预览1. 修改代码2. 查看sonarqube检查结果3. 查看nexus仓库4. 查看harbor仓库5.…

【打卡】Datawhale暑期实训ML赛事

文章目录 赛题描述任务要求数据集介绍评估指标 赛题分析基于LightGBM模型Baseline详解改进baseline早停法添加特征 赛题描述 赛事地址&#xff1a;科大讯飞锂离子电池生产参数调控及生产温度预测挑战赛 任务要求 初赛任务&#xff1a;初赛提供了电炉17个温区的实际生产数据&…