【c++】运算符重载实例

news2024/10/1 1:54:08

重载自增自减运算符

Intger num(2);
num++;
++num;

对自增运算符的重载要区分前置和后置。在重载之前需要思考一个问题,num++是返回一个临时变量还是num对象的本体。

为了解决这个问题可以考虑实现一个Inc_()函数和_Inc()函数分别模仿后置++和前置++的行为

Integer Inc_(){
    int t=this->_num;
    this->_num+=1;        
    return Integer(t);
}
Integer& _Inc(){
    this->_num++;
    return *this;
}

分别调用这两个函数

Integer num(3);
auto t=num.Inc_();
std::cout<<t.getValue();

调用Inc()_输出结果如下
在这里插入图片描述

Integer num(3);
auto t=num._Inc();
std::cout<<t.getValue();

调用_Inc()输出结果如下
在这里插入图片描述

通过这个例子不难看出后置++返回的是临时对象,前置++返回的是本体。

接下来就开始重载前置++和后置++

Integer operator++(){//后置++
        int t=this->_num;
        this->_num+=1;
        return Integer(t);
}
Integer& operator++(){//前置++   
    this->_num++;
    return *this;
}

但是如果这样写就会报错,因为函数重载是通过参数列表进行区分的,而不是通过返回值类型进行区分。
在这里插入图片描述

通常对于后置++要使用站位参数

Integer operator++(int){//后置++
    int t=this->_num;
    this->_num+=1;
    return Integer(t);
}

重载逻辑运算符和单目运算符

逻辑与

bool operator&&(const Integer&right)const
{
    return this->_num&&right._num;
}
std::cout<<std::boolalpha<<(Integer(0)&&Integer(1));

在这里插入图片描述

单目负

Integer operator -(){
    return Integer(-this->_num);
}

括号运算符

()函数调用运算符

重载了这运算符,对象就有了函数的行为(仿函数)

class Program
{
public:
    void operator()(){//第一个括号是运算符
        std::cout<<"hello world";
    }
};
Program p;
p();//调用括号运算符

在这里插入图片描述

重载括号运算符是可以有参数的

class Program
{
public:
    void operator()(int i){//第一个括号是运算符
        std::cout<<"i="<<i<<"hello world";
    }
};

在这里插入图片描述
说明

  • 函数调用运算符只能用非静态成员函数重载
  • 函数调用运算符可以有任意个参数,但不能有默认参数

[]下标访问运算符

class String
{
private:
    int size;
    char*str;
public:
    
    String(const char*str)
    {
        size=strlen(str);
        this->str=new char[size+1]{0};
        strcpy(this->str,str);
    }
    int Size(){return size;}
};
int main()
{
    String str="hello world";
    return 0;
}

假设现在要有这样的一个操作

//循环遍历str内部的字符串
for(int i=0;i<str.Size();i++)
{
    //to do
}

这个时候如何重载了下标访问运算符就可以通过str[i]遍历内部的字符串,这样操作是不是就相当方便了

char& operator[](int i){
    return str[i];
}

说明

  • []是一个二元运算符,具有数组名和下标两个参数,数组名由编译器通过this指针隐式传递,因此参数表中只需要提供一个参数。
  • []可以同时出现在赋值运算符左边和右边,所以重载是常常返回引用,因为返回引用的函数可以出现在=的左边调用。
  • 只能用非静态成员函数重载

和指针有关的运算符

int main()
{
    int*a=new int[5];
    return 0;
}

上面的这个程序进行new操作后没有delete会造成内存泄漏,但如果就是忘掉了delete呢?这个可以通过自己实现一个类来解决这个问题。

class Auto_Ptr
{
public:
    Auto_Ptr(int*ptr):m_ptr(ptr){}
    ~Auto_Ptr(){delete m_ptr;}
private:
    int*m_ptr;
};
int*a=new int[5];
Auto_Ptr pa(a);

Auto_Ptr这个类帮我们完成了delete操作,这样就不用担心new了之后忘记delete了。
那么如何让Auto_Ptr则个类更像指针,那么就要重载一些运算符

class People
{
private:
    int age_;
    std::string name_;
public:
    
    People(const std::string name,int age)
		:name_(name),age_(age)
	{}
    
    std::string name()const{return name_;}
};
class Auto_Ptr
{
public:
    Auto_Ptr(People*ptr):m_ptr(ptr){}
    ~Auto_Ptr(){delete m_ptr;}
    People *operator->(){
        return m_ptr;
    }
    People *operator&(){
        return m_ptr;
    }
    People operator*(){
        return m_ptr[0];
    }
private:
    People*m_ptr;
};

在这里插入图片描述

总结

  1. 目的:为已有的运算符赋予新的含义,以方便我们使用。
  2. 实质:函数重载的一种形式,或者说是一种特殊的函数。
  3. 规则:
    • 只能重载C++中已经定义好的运算符。
    • 不能创建新的运算符。
    • 运算符重载后,其优先级、结合性等保持不变。
    • 不能改变运算符的语法结构。
  4. 重载运算符的函数原型:返回类型 operator 运算符 (参数列表)。
  5. 重载运算符的参数:可以有一个或多个参数。当运算符有多个参数时,参数之间用逗号隔开。
  6. 重载运算符的返回类型:可以是任何数据类型,包括基本数据类型和自定义类型。
  7. 运算符重载的方法:
    • 前缀形式:例如,重载++运算符时,函数名为 operator++()。
    • 后缀形式:例如,重载++运算符时,函数名为 operator++(int)。注意,这里的int是虚拟参数,并不代表真实的类型。
      注意事项:
  8. 重载的运算符必须与用户使用的输入匹配。如果用户使用了不同的输入,则不会调用该重载的运算符。
  9. 应该小心使用复杂的运算符重载,因为这可能导致程序的可读性和可维护性下降。如果发现自己在重载运算符时使用了过多的参数或者做出了过于复杂的操作,那么可能需要重新考虑一下设计。
  10. 在重载运算符时,需要确保不会破坏原有运算符的语义和语法规则。例如,你不能改变运算符的优先级或结合性。
    在重载运算符时,需要确保重载后的运算符能够与使用它的代码和谐共存。例如,你不能让重载后的运算符破坏了原有代码的结构或者逻辑。

总的来说,虽然运算符重载提供了很大的灵活性,但是需要谨慎使用,以避免引入不必要的复杂性。在重载运算符时,应该尽量保持原有的语义和语法规则,以确保代码的可读性和可维护性。

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

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

相关文章

Calibre拾遗:FDI (Foreign Database Interface)系统简介

Calibre是强大的GDS处理工具&#xff0c;包括查看&#xff0c;验证&#xff0c;分析等操作&#xff0c;操作由浅入深&#xff0c;除过手动编辑GDS的不是很灵活外&#xff0c;其他各种命令和操作策略&#xff0c;都是远&#xff08;遥&#xff09;远&#xff08;遥&#xff09;走…

使用create-vue创建项目

认识create-vue create-vue是Vue官方新的脚手架工具&#xff0c;底层切换到了vite&#xff08;下一代构建工具&#xff09;&#xff0c;为开发提供极速响应。 使用create-vue创建项目 1.前提环境条件 已安装16.0或更高版本的Node.js node -v 2.创建一个Vue应用 npm init…

Monocular arbitrary moving object discovery and segmentation 论文阅读

基本信息 题目&#xff1a;Monocular Arbitrary Moving Object Discovery and Segmentation 作者&#xff1a; 来源&#xff1a;BMVC 时间&#xff1a;2021 代码地址&#xff1a;https://github.com/michalneoral/Raptor Abstract 我们提出了一种发现和分割场景中独立移动的…

[算法训练营] 回溯算法专题(一)

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的…

Linux系列讲解 —— VIM配置与美化

目录 1. Vim基本配置1.1 配置文件1.2 基本配置 2. 插件管理器Vundle2.1 下载Vundle2.2 在vimrc中添加Vundle的配置 3. Vundle的使用3.1 安装插件3.2 卸载插件 1. Vim基本配置 1.1 配置文件 vim的配置文件有两处&#xff0c;请根据实际情况选择修改哪个。 (1) 全局配置文件&am…

电子元器件管理系统 JAVA语言开发

目录 一、系统介绍 二、系统下载 三、系统截图 一、系统介绍 基于VueSpringBootMySQL的电子元器件管理系统包含元器件单位模块、元器件仓库模块、元器供应商模块、元器件品类模块、元器件明细模块、元器件采购模块、元器件采购审核模块、元器件领用模块、学生元器件申请模块…

前端AJAX入门到实战,学习前端框架前必会的(ajax+node.js+webpack+git)(二)

阳光总在风雨后&#xff0c;请相信有彩虹。 案例 - 图书管理 bootstrap弹框 需求&#xff0c;点击添加按钮&#xff0c;没有离开当前页面&#xff0c;在当前页面弹出弹框&#xff08;弹窗&#xff09; 先学着实现一个简单的弹框&#xff0c;如下图右下角 bootstrap有两种方式…

openGauss学习笔记-108 openGauss 数据库管理-管理用户及权限-用户

文章目录 openGauss学习笔记-108 openGauss 数据库管理-管理用户及权限-用户108.1 创建、修改和删除用户108.2 私有用户108.3 永久用户108.4 用户认证优先规则 openGauss学习笔记-108 openGauss 数据库管理-管理用户及权限-用户 使用CREATE USER和ALTER USER可以创建和管理数据…

解决虚拟机联网问题

虚拟机开机后发现右上角缺少联网标志(下面有正常联网标志)&#xff0c;这样就是连不上网的 不信你可以打开Ubuntu里面的浏览器或ping www.baidu.com 1.编辑虚拟机设置-->网络适配器-->如图所示 2.选择编辑-->虚拟网络编辑器 3.更改设置 4此处可以选择还原默认设置&am…

【JAVA学习笔记】42 - 内部类(难点,重点)

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter10/src/com/yinhai/innerclass_ 一、基本介绍 一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类(inner class),嵌套其他类的类称为外部类(outer class)。是我们类的第五大成…

【蓝桥每日一题]-动态规划 (保姆级教程 篇12)#照相排列

这次是动态规划最后一期了&#xff0c;感谢大家一直以来的观看&#xff0c;以后就进入新的篇章了 目录 题目&#xff1a;照相排列 思路&#xff1a; 题目&#xff1a;照相排列 思路&#xff1a; 首先记录状态f[a][b][c][d][e]表示每排如此人数下对应的方案数&#xff0c;然…

java中按行读取文件内容

java中按行来读取文件内容&#xff0c;一般对文件也是又要求的&#xff0c;比如文件编码utf-8&#xff0c;内容是按行可读&#xff0c;而不是一堆字节码。这类文件&#xff0c;我们按行读取&#xff0c;主要是方便快速查看内容&#xff0c;并且用这些内容来作别的用途&#xff…

FileUpload控件上传文件时出现 不支持给定路径的格式.的解决方法

正常代码&#xff0c;部署到server 2012时&#xff0c;在上传音频mp3文件时&#xff0c;显示错误“不支持给定路径的格式”&#xff0c;上传控件使用FileUpload控件&#xff1a; 因为程序之前是正常的&#xff0c;因此应该不是程序的问题。 上传时&#xff0c;发现在选择文件时…

F28335-可移植新建工程模板-基于bitfield

文章目录 前言步骤新建工程工程管理拷贝底层文件 添加测试函数编写main.c测试函数 前言 实验要求利用28335芯片&#xff0c;重新学习一下DSP28335&#xff0c;并做个记录。 值得一提的是&#xff0c;28335只能用寄存器开发&#xff0c;而不能用库函数开发&#xff0c;相应的也…

LDAP注入漏洞

1、LDAP 注入 LDAP (Light Directory Access Portocol) 是基于X.500标准的轻量级目录访问协议&#xff0c;提供访问目录数据库方法的服务和协议&#xff0c;常用于与目录数据库组成目录服务。其中目录是一个为查询、浏览和搜索而优化的专业分布式数据库&#xff0c;它呈树状结…

Java学习 1.初识Java

1.类名 当这个类被public修饰时 class后的名字 类名必须和文件名相同 public class 类名(文件名); 2.main函数 方法一定是包含在类之中的 3.类里面是函数/方法 由返回值、方法名、参数列表组合而成,方法中可以定义变量&#xff0c;方法体 4.一个文件中可以有多个类 我们建…

【管理运筹学】第 10 章 | 排队论(3,标准的 M/M/1 排队系统)

文章目录 引言一、模型特征及分析二、系统指标1. 在系统中的平均顾客数&#xff08;队长的期望&#xff09;2. 在队列中的平均顾客数&#xff08;队列长的期望&#xff09;3. 在系统中顾客平均逗留时间4. 在队列中顾客的平均等待时间 写在最后 引言 前两篇文章&#xff0c;分别…

李沐——论文阅读——VIT(VIsionTransformer)

一、终极结论&#xff1a; 如果在足够多的数据上面去做预训练&#xff0c;那么&#xff0c;我们也可以不用 卷积神经网络&#xff0c;而是直接用 自然语言处理那边搬过来的 Transformer&#xff0c;也能够把视觉问题解决的很好 &#xff08;tips&#xff1a;paperswithcode.co…

【刷题-PTA】堆栈模拟队列(代码+动态图解)

【刷题-PTA】堆栈模拟队列(代码动态图解) 文章目录 【刷题-PTA】堆栈模拟队列(代码动态图解)题目输入格式:输出格式:输入样例:输出样例: 分析题目区分两栈解题思路伪代码动图演示代码测试 题目 题目描述 : 设已知有两个堆栈S1和S2&#xff0c;请用这两个堆栈模拟出一个队列Q。 …

新华三路由器+华为交换机,实现华为交换机指定端口访问外网

需求背景&#xff1a; 多台服务器使用华为交换机组建了局域网&#xff0c;需要让交换机的指定端口可以访问外网。 需求分析&#xff1a; 交换机组建的局域网是二层组网&#xff0c;需借助路由器接入外网&#xff0c;然后通过DHCP分配内网IP地址给交换机指定端口连接的设备。 …