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

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.不能重载的运算符

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

OpenHarmony实战开发-使用SmartPerf-Host分析应用性能

简介 SmartPerf-Host是一款深入挖掘数据、细粒度展示数据的性能功耗调优工具&#xff0c;可采集CPU调度、频点、进程线程时间片、堆内存、帧率等数据&#xff0c;采集的数据通过泳道图清晰地呈现给开发者&#xff0c;同时通过GUI以可视化的方式进行分析。该工具当前为开发者提…

docker在linux上的安装与使用

我的操作系统centos7本地vm docker安装 1、卸载旧版本 如果系统中已经存在旧的Docker&#xff0c;则先卸载 yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine 2、配置一…

Android 音视频基础知识

本系列文章会介绍两个 Android NDK Demo&#xff0c;拉流端会实现一个基于 FFmpeg 的视频播放器 Demo&#xff0c;推流端会实现一个视频直播 Demo&#xff0c;当然在做 Demo 之前会介绍音视频的基础知识。以下是本系列文章的目录&#xff1a; Android 音视频基础知识 Android 音…

【langchain】快速封装替换自定义LLM(基于自定义API或本地模型)

1. 引言 你可能已经注意到&#xff0c;LLM时代下的许多项目&#xff08;特别是Github上的论文项目、工程项目&#xff09;都要求我们设置OpenAI的API Key&#xff0c;就像这样&#xff1a; os.environ["OPENAI_API_KEY"] "sk-"from langchain_openai im…

SDKMAN!

概述 官网&#xff0c;SDKMAN是一款管理多版本SDK的工具&#xff0c;可以实现在多个版本间的快速切换。 其他特性&#xff1a; 易用&#xff1a;安装SDK不再需要去Google想安装的某个软件的官网的下载页&#xff0c;或找其他下载页面&#xff0c;然后下载安装包、解压、设置…

.NET C# ORM 瀚高数据库

SqlSugar ORM SqlSugar 是一款 老牌 .NET开源ORM框架&#xff0c;由果糖大数据科技团队维护和更新 &#xff0c;开箱即用最易上手的ORM 优点 &#xff1a;【生态丰富】【高性能】【超简单】 【功能全面】 【多库兼容】【适合产品】 【SqlSugar视频教程】 支持 &#xff1a…

C语言指针和数组的一些笔试题

文章目录 前言一、一维数组二、字符数组-1三、字符数组-2总结 前言 C语言指针和数组的一些笔试题 一、一维数组 #include <stdio.h> int main() {int a[] { 1,2,3,4 };printf("%d\n", sizeof(a));printf("%d\n", sizeof(a 0));printf("%d\n…

Eclipse MAT工具分析内存溢出

1、通过dominator_tree可以查看哪些对象大 可以看到com.codex.terry.entity.User对象有57万个 2、打开thread_overview查看内存溢出的代码

TCP重传,滑动窗口,流量控制,拥塞控制

TCP重传&#xff0c;滑动窗口&#xff0c;流量控制&#xff0c;拥塞控制 TCP重传机制&#xff1a; 超时重传快速重传SACKD-SACK 通过序列号与确认应答判断是否要重传 超时重传&#xff1a; 超过指定时间没有收到确认应答报文&#xff0c;就会重发该数据 触发超时重传的情况…

(十四)Servlet教程——Servlet中HttpSession的使用

除了使用Cookie&#xff0c;Web应用程序中还经常使用Session来记录客户端状态。Session是服务器端使用的一种记录客户端状态的机制&#xff0c;相应地也增加了服务器的存储压力。 1. 什么是Session Session是另外一种记录客户端状态的机制&#xff0c;不同的是Cookie保存在客户…

2024年618哪些数码家电值得入手?热门家电好物抢先看!

618购物狂欢节即将来临&#xff0c;这是一年一度的大促销活动&#xff0c;家电和数码产品在这个时间段内通常都会有优惠和折扣。但随着产品的多样化&#xff0c;很多时候一款产品就有多款品牌&#xff0c;在这不同品牌又各自擅长不同的东西&#xff0c;看着眼花缭乱。今天我就给…

基于python+django网易新闻+评论的舆情热点分析平台

博主介绍&#xff1a; 大家好&#xff0c;本人精通Java、Python、C#、C、C编程语言&#xff0c;同时也熟练掌握微信小程序、Php和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我有丰富的成品Java、Python、C#毕设项目经验&#xff0c;能够为学生提供各类…

Java中优雅实现泛型类型的强制转换

在Java中经常遇到将对象强制转换成泛型类的情况&#xff1a; Map<String, Object> data Map.of("name", "XiaoMing","age", 17,"scores", List.of(80, 90, 70) );List<Integer> scores (List<Integer>) data.get…

Docker容器添加修改端口映射的方法与详细步骤

1、先找到要修改的容器hash值&#xff1a; 2、然后退出docker Desktop服务 &#xff08;因为在线状态配置文件修改保存不了&#xff09; 3、资源管理器中打开最新安装的Docker的配置文件的路径&#xff1a; 4、打开后修改其中的 config.v2.json 和 hostconfig.json 5、启动…

【C++】哈希表的底层逻辑

目录 一、哈希概念 1、哈希冲突 2、哈希冲突的解决 a、闭散列 &#x1f7e2;插入 &#x1f7e2;查找 &#x1f7e2;删除 &#x1f7e2;其他类型的数据 &#x1f7e2;实现 b、 开散列 &#x1f7e2;插入 &#x1f7e2;查找 &#x1f7e2;删除 &#x1f7e2;析构 &a…

《霍格沃茨之遗》找不到emp.dll如何修复?分享5种亲测有效的方法

在我们享受电脑游戏带来的乐趣时&#xff0c;偶尔会遇到一些技术上问题&#xff0c;具体来说&#xff0c;当你启动一款游戏&#xff0c;系统却弹出一个提示“由于找不到emp.dll文件&#xff0c;因此无法继续执行代码”&#xff0c;这样的情况确实让人感到扫兴。这究竟是什么原因…

.net core ef 连表查询

Information和TypeInfo连表查询 类似&#xff1a; select st.Title1,si.* from [Star_Information] si left join Star_TypeInfo st on si.typeId2st.id 先在EfCoreDbContext.cs配置 protected override void OnModelCreating(ModelBuilder builder){base.OnModelCreating(b…

Jupyter Notebook 中使用虚拟环境的Python解释器

问题&#xff1a;创建虚拟环境&#xff0c;在pycharm中配置虚拟环境的Python解释器&#xff0c;然后在pycharm中打开ipynb&#xff0c;执行发现缺少包&#xff0c;但是虚拟环境中已经安装了 解决方式&#xff1a; 配置Jupyter Notebook 使用虚拟环境的Python解释器 1&#x…

ElasticSearch总结2

一、创建索引库&#xff1a;PUT ES中通过Restful请求操作索引库、文档。请求内容用DSL语句来表示。创建索引库和mapping的DSL语法如下&#xff1a; 整个jason 里边&#xff0c;它有一个叫mapping的属性&#xff0c;代表的是映射。映射里边有properties代表就是字段。可以看到这…

C++入门系列-缺省参数

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 缺省参数的概念 缺省参数是生命或者定义函数时为函数的参数指定一个缺省值&#xff0c;在调用该函数时&#xff0c;如果没有指定实参则采用该形参的缺省值&#xff0c;否则使用…