《21天学通C++》(第十二章)运算符类型与运算符重载

news2024/11/20 20:23:29

1.为什么要重载运算符?

通过重载运算符,可以将复杂的操作封装成简单的运算符形式,简化代码,提高可读性下面举一个简单的例子

计算两个点的坐标之和。

1.不重载运算符

#include <iostream>  
using namespace std; 

class Point { 
public:
    int x, y;  // Point类的成员变量,表示点的x和y坐标

    // 构造函数,初始化x和y坐标
    Point(int x, int y) : x(x), y(y) {}

    // 成员函数,用于计算两个点的坐标之和并返回新的Point对象
    Point add(const Point& other) const {
        return Point(x + other.x, y + other.y);  
        // 返回一个新Point,其坐标为当前对象和other对象坐标的和
    }
};

int main() {
    Point p1(1, 2);  // 创建一个Point对象p1,坐标为(1, 2)
    Point p2(3, 4);  // 创建另一个Point对象p2,坐标为(3, 4)

    // 使用成员函数add来计算两个点的坐标之和,并将结果赋值给p3
    Point p3 = p1.add(p2);

    // 使用cout输出p3的坐标,格式为"(x, y)"
    cout << "The sum of p1 and p2 is: (" << p3.x << ", " << p3.y << ")" << endl;
    system("pause");
    return 0; 
}

2.使用重载运算符

#include <iostream> 
using namespace std; 

class Point { 
public:
    int x, y; 

    // 构造函数,用于初始化点的x和y坐标
    Point(int x, int y) : x(x), y(y) {}

    // 重载 "+" 运算符,使其能够用于Point类的对象
    // 这个函数接受一个Point对象作为参数,并返回一个新的Point对象
    // 新对象的坐标是原两个Point对象坐标的和
    Point operator+(const Point& other) const {
        return Point(x + other.x, y + other.y); 
    // 返回一个新的Point对象,其坐标为当前对象和other对象坐标的和
    }
};

int main() {
    Point p1(1, 2);  // 创建一个Point对象p1,其坐标为(1, 2)
    Point p2(3, 4);  // 创建另一个Point对象p2,其坐标为(3, 4)

    // 使用重载的 "+" 运算符来计算两个Point对象的坐标之和
    // 这行代码等价于调用 p1.add(p2),但由于运算符重载,我们可以直接使用 + 号
    Point p3 = p1 + p2;
    
    cout << "The sum of p1 and p2 is: (" << p3.x << ", " << p3.y << ")" << endl;
    system("pause");
    return 0; 
}

重载运算符后可以使用+来进行坐标点的运算,代码更加简洁,可读性更高

2.单目运算符

即只能对一个操作数进行操作

单目运算符的类型
在这里插入图片描述
单目递增与单目递减运算符
一个可以对日期进行递增和递减的操作,代码如下:

#include <iostream>
using namespace std;

class Date {
private:
    int day;
    int month;
    int year;

    // 简化版的日期合法性检查
    void checkDate() {
        // 如果是2月28日,增加到3月1日
        if (month == 2 && day == 29) {
            day = 1;
            month = 3;
        }
        // 如果月份超过12,增加年份
        if (month > 12) {
            month = 1;
            year++;
        }
    }

public:
    // 构造函数
    Date(int d, int m, int y) : day(d), month(m), year(y) {
        checkDate();
    }

    // 单目递增运算符重载
    Date& operator++() {
        day++;
        checkDate();
        return *this;
    }

    // 成员函数用于输出日期
    void diplayDate() const {
        cout << day << "/" << month << "/" << year;
    }
};

int main() {
    Date today(28, 2, 2024); // 今天是2024年2月28日

    today.diplayDate(); // 使用成员函数输出日期
    cout << endl; // 输出换行
    ++today;       // 使用重载后的递增运算符
    today.diplayDate(); // 使用成员函数输出日期
    cout << endl; // 输出换行
    system("pause");
    return 0;
}

PS: 还可以使用后缀运算符,但如果只是想执行递增递减运算,应当选择前缀运算符。
因为在后缀运算符中,首先会复制当前对象,再对当前对象执行递增递减运算,最后返回复制对象,会多一步临时拷贝的步骤,且这个创建的临时拷贝也不会被使用

3.转换运算符

示例代码如下:

#include <iostream>
#include <sstream>
#include <string>
using namespace std;

class Date {
private:
    int day;
    int month;
    int year;
    string dateInString; // 用于存储格式化后的日期字符串

    // 简化版的日期合法性检查
    void checkDate() {
        // 如果是2月28日,增加到3月1日(这里不考虑闰年)
        if (month == 2 && day == 29) {
            day = 1;
            month = 3;
        }
        // 如果月份超过12,增加年份
        if (month > 12) {
            month = 1;
            year++;
        }
    }

public:
    // 构造函数,初始化日期并检查合法性
    Date(int d, int m, int y) : day(d), month(m), year(y) {
        checkDate();
    }

    // 单目递增运算符重载,将日期递增一天
    Date& operator++() {
        day++;
        checkDate();
        return *this;
    }

    // 类型转换运算符,将Date对象转换为const char*类型
    // 这样,Date对象可以直接被ostream类使用,如cout
    operator const char* (){
        // 使用ostringstream将日期转换为字符串
        ostringstream oss;
        oss << month << "/" << day << "/" << year;
        // 将转换后的字符串存储在dateInString中
        dateInString = oss.str();
        // 返回字符串的C风格字符数组(const char*)
        return dateInString.c_str();
    }
};

int main() {
    Date today(28, 2, 2024); 
    // 使用类型转换运算符将Date对象转换为const char*,并使用cout输出
    cout << "Tomorrow's date: " << today << endl;
   
    system("pause");
    return 0;
}

通过类型转化后,可以使用cout直接输出

4.双目运算符

可以对两个操作数进行操作的运算符
在这里插入图片描述

5.函数运算符operator()

函数运算符允许类的实例表现得就函数一样,可以接受参数返回结果

#include <iostream>
#include <string>

class SimpleFunc {
public:
    // 重载()运算符,使其可以像函数一样被调用
    int operator()(int a, int b) {
        return a + b; // 这里我们简单地返回两个数的和
    }
};

int main() {
    SimpleFunc func; // 创建SimpleFunc的实例

    // 使用SimpleFunc实例来计算两个数的和
    int result = func(3, 5); // 调用func对象,传入3和5作为参数

    // 输出结果
    std::cout << "The sum of 3 and 5 is: " << result << std::endl;
    system("pause");
    return 0;
}

6.移动构造函数和移动赋值运算符

移动构造函数和移动赋值运算符是性能优化功能,用于高性能编程,属于C++11标准的一部分,旨在避免复制不必要的临时值

移动构造函数: 移动构造函数是一个接受一个同类型对象的右值引用作为参数的构造函数。它的主要目的是在对象的构造过程中,将资源从另一个对象“移动”过来,而不是进行复制

class MyClass {
public:
    MyClass(MyClass&& other) noexcept {//声明方法
        // 移动资源
    }
};

移动赋值运算符: 移动赋值运算符是一个接受一个同类型对象的右值引用作为参数的赋值运算符。它允许一个对象通过接管另一个对象的资源来改变其状态,而不是通过复制

class MyClass {
public:
    MyClass& operator=(MyClass&& other) noexcept {//声明方法
        // 移动资源并赋值
        return *this;
    }
};

7.不能重载的运算符

在这里插入图片描述

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

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

相关文章

JavaScript基础(四)

逻辑运算符 && 与 : 多个条件同时满足 ΙΙ 或 : 多个条件满足一个 &#xff01; 非 : 否定某个条件 例: <script> //&多个条件同时满足&#xff0c;才返回true //任意一个为false&#xff0c;就返回false var a 10; var b 20; …

【linux】重定向

重定向 什么是重定向如何实现一个简单的重定向关于重定向的系统调用接口 注意&#xff1a;在看这篇博客之前&#xff0c;最好是要对文件在系统中是如何被打开的以及操作系统是如何管理文件有一个初步了解&#xff0c;如果不了解的话&#xff0c;可以看看这篇博客《初步认识文件…

stm32之hal库spi驱动封装(实现阻塞,中断,dma三种方式)

前言 配置功能参考rt-thread驱动代码将中断配置和dma配置单独分开管理 代码 中断管理 头文件 /** Copyright (c) 2024-2024,shchl** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author Notes* 2024-5-3 shchl first version*/#ifnd…

【AIGC】本地部署 ollama + open-webui

在之前的篇章《【AIGC】本地部署 ollama(gguf) 与项目整合》中我们已经使用 ollama 部署了一个基于预量化&#xff08;gguf&#xff09;的 Qwen1.5 模型&#xff0c;这个模型除了提供研发使用外&#xff0c;我还想提供给公司内部使用&#xff0c;因此还需要一个 ui 交互界面。 …

2003-2022年各省对外直接投资存量/省对外直接投资流量/省OFDI流量/省OFDI存量数据

2003-2022年各省对外直接投资存量、省对外直接投资流量、省OFDI流量、省OFDI存量数据 1、时间&#xff1a;2003-2022年 2、来源&#xff1a;对外直接投资公报 3、范围&#xff1a;31省 4、指标&#xff1a;省对外直接投资流量/OFDI流量、省对外直接投资存量/OFDI存量 5、指…

OpenCV(三)—— 车牌筛选

本篇文章要介绍如何对从候选车牌中选出最终进行字符识别的车牌。 无论是通过 Sobel 还是 HSV 计算出的候选车牌都可能不止一个&#xff0c;需要对它们进行评分&#xff0c;选出最终要进行识别的车牌。这个过程中会用到两个理论知识&#xff1a;支持向量机和 HOG 特征。 1、支…

爬虫自动化之drissionpage实现随时切换代理ip

目录 一、视频二、dp首次启动设置代理三、dp利用插件随时切换代理一、视频 视频直接点击学习SwitchyOmega插件使用其它二、dp首次启动设置代理 from DrissionPage import ChromiumPage, ChromiumOptions from loguru

MySQL与金蝶云星空对接集成执行查询语句-v2打通销售退货新增V1

MySQL与金蝶云星空对接集成执行查询语句-v2打通销售退货新增V1 数据源系统:MySQL mysql是一个关系数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;所谓的关系型数据库&#xff0c;是建立在关系模型基础上的数据库&#xff0c;借助于集合代数等数学概念和方法来处理数…

深度解析 Spring 源码:探寻Bean的生命周期

文章目录 一、 Bean生命周期概述二、Bean生命周期流程图三、Bean生命周期验证3.1 代码案例3.2 执行结果 四、Bean生命周期源码4.1 setBeanName()4.2 setBeanFactory()4.3 setApplicationContext()4.4 postProcessBeforeInitialization()4.5 afterPropertiesSet()4.6 postProces…

npm安装依赖报错解决办法

项目场景&#xff1a; 安装gitee上的开源vue3TS项目&#xff0c;npm安装依赖报错 问题描述 克隆项目到VSCode之后&#xff0c;使用npm install安装依赖&#xff0c;报错 npm install npm ERR! code ENOENT npm ERR! syscall open npm ERR! path Y:\WebStudyBlog\MovieWeb/p…

【Linux】学习笔记

文章目录 [toc]第一章&#xff1a;基础篇01|课程介绍02|内容综述03|什么是Linux04|Linux的内核版本及常见发行版内核版本发行版本Red Hat Enterprise LinuxFedoraCentOSDebianUbuntu 05|安装VirtualBox虚拟机VirtualBox下载url 06|在虚拟机中安装Linux系统Linux安装镜像下载 07…

基于OpenCv的图像傅里叶变换

⚠申明&#xff1a; 未经许可&#xff0c;禁止以任何形式转载&#xff0c;若要引用&#xff0c;请标注链接地址。 全文共计3077字&#xff0c;阅读大概需要3分钟 &#x1f308;更多学习内容&#xff0c; 欢迎&#x1f44f;关注&#x1f440;【文末】我的个人微信公众号&#xf…

【C++并发编程】(四)条件变量

文章目录 &#xff08;四&#xff09;条件变量 &#xff08;四&#xff09;条件变量 条件变量&#xff08;Condition Variable&#xff09;用于线程间的同步&#xff0c;允许一个或多个线程在特定条件不满足时等待&#xff0c;并在条件满足时被其他线程唤醒。C标准库中提供了的…

D3CTF2024

文章目录 前言notewrite_flag_where【复现】D3BabyEscapePwnShell 前言 本次比赛笔者就做出两道简单题&#xff0c;但队里师傅太快了&#xff0c;所以也没我啥事。然后 WebPwn 那题命令行通了&#xff0c;但是浏览器不会调试&#xff0c;然后就简单记录一下。 note 只开了 N…

【热门话题】如何构建具有高度扩展性的系统

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 如何构建具有高度扩展性的系统引言一、理解扩展性1.1 扩展性的定义1.2 扩展性的…

3GPP官网下载协议步骤

1.打开官网 https://www.3gpp.org/ 2.点击 3.在界面选择要找的series&#xff0c;跳转到查找界面 以V2X通信协议为例&#xff0c;论文中通常会看到许多应用&#xff1a; [7] “Study on evaluation methodology of new Vehicle-to-Everything (V2X) use cases for LTE and NR…

2-手工sql注入(进阶篇) sqlilabs靶场1-4题

1. 阅读&#xff0c;学习本章前&#xff0c;可以先去看看基础篇&#xff1a;1-手工sql注入(基础篇)-CSDN博客 2. 本章通过对sqlilabs靶场的实战&#xff0c;关于sqlilabs靶场的搭建&#xff1a;Linux搭建靶场-CSDN博客 3. 本章会使用到sqlmap&#xff0c;关于sqlmap的命令&…

C 深入指针(2)

目录 1 野指针 1.1 成因 1.2 如何规避野指针 2 assert 断言 2.1 用法 2.2 assert 的优点 2.1 assert 的缺点 3 小注解 3.1 Debug 和 Release 1 野指针 【概念】&#xff1a; 野指针就是指针指向的位置是不可知的&#xff08;随机的、不正确的、没有明确限制的&#…

解决windows下无法安装Hyper-V

在windows中打开hyper-v的办法如下&#xff1a;&#xff08;但不适用无法安装hyper-v的windows系统如win10家庭版&#xff09; 通过「控制面板」是启用 Hyper-V 最直接的方法&#xff1a; 1 使用Windows R快捷键打开「运行」对话框&#xff0c;执行appwiz.cpl以打开「控制面…

关于win平台c语言引入开源库的问题与解决

许久不写博客&#xff0c;五一还在加班&#xff0c;就浅浅写一篇吧 最近除了做物联网平台 还对网关二次开发程序做了修改&#xff0c;网关的二次开发去年年底的时候做过&#xff0c;但是当时的逻辑不是十分完善&#xff0c;差不多已经过了半年了&#xff0c;很多细节已经忘记了…