C++学习笔记总结练习:运算符重载两种方式

运算符重载的两种方式

1 基本概念

基础

  • 运算符时具有特殊名字的函数:由关键字operator和气候定义的运算符共同组成。

  • 可以被重载的运算符

在这里插入图片描述

方式

  1. 将运算符重载为类的成员函数
  2. 重载运算符函数,并声明为类的友元

规则

  1. 重载后的运算符必须至少有一个操作数是用户定义的类型,这是为了防止程序员为标准类型重载运算符,可以确保程序正确运行。

  2. 不能修改运算符的优先级,不能违反运算符原本的运算规则。例如在重载加号时,不能提供两个形参(友元除外),例如下面的这种重载方式就是不被允许的;因为加法是一种双目运算符。在重载为类的成员函数后,加法运算的第一项应该是调用函数的一个对象。所以在运算符重载时,参数表中的参数数目应该是重载运算符的操作数减1。

Time operator+(const Time &t1,const Time &t2) const;
  1. 不能创造新的运算符,例如不能定义operator**()运算符;
  2. 不能重载以下运算符;
.:成员运算符
.*:成员指针运算符
:: :作用域运算符
?::条件运算符
siezof:sizeof运算符。
  1. 很多运算符可以通过成员或者非成员函数进行重载,但是以下四种只能通过成员函数进行重载;
=:赋值运算符;
( ):函数调用运算符;
[ ]: 下标运算符
->:通过指针方位类成员的运算符。
  1. 自增运算符(++)与自减运算符(–)由于自增和自减运算符是单目运算符,在重载时应该是没有参数的,但是又有前置与后置之分,例如++i与i++。为了隽星区分,C++做了规定;
Time operator++()      //前置
Time operator++(int)   //后置

2 成员函数重载

成员函数重载格式

  • 将操作符重载为成员函数。
  • 此时类的对象作为操作符的第一个操作数。流输入输出运算符无法通过这样的方式重载,因为对象本身应该作为第二个操作数,只能通过友元函数的方式对操作进行重载。
class MyString{
public:
    // 重载等号运算符
    MyString& operator=(const MyString &b);
    // 重载+=运算符
    MyString& operator+=(const MyString &b);
}

3 友元重载

友元的格式

C++中友元有三种,分别是友元函数,友元类,友元成员函数,这里介绍的是友元函数。

  1. 创建友元函数的第一步是声明,友元函数的声明放在类的声明中,并且在前面加上friend关键字。例如;
friend ostream& operator<<(ostream &os, const Time &t);
  1. 第二步是定义友元,友元可以直接在声明的时候进行定义,即内联的定义。也可以定义在类外,定义在类外时,不需要加类作用域运算符,也不需要有friend关键字。
//友元在类外定义的时候,不需要添加friend;
ostream & operator<<(ostream &os, const Time &t)  
{
	os << "hours:" << t.hours << "  " << "mintues:" << t.mintues << "  ";
	return os;
}

友元使用

与普通的运算符重载成员函数一样,友元也可以直接调用

cout<<time1<<time2;//等价于
operator<<(operator<<(cout,time1),time2);

4 实例——MyString的实现

/* 
* C++ string 类的实现
* 1. 构造函数和析构函数
* 2. 字符串长度
* 3. 重载=运算符
* 4. 重载+=运算符
* 5. 重载<< >> 运算符
* 6. 重载比较运算符
* 7. 重载[]下标运算符
*/

#include <iostream>
#include <cstring>
using namespace std;

class MyString
{
private:
    char * str;
    int length;
public:
    // 长度
    int size ()const {
        return length;
    };
    char* getstr()const{
        return str;
    }
    // 默认构造函数
    MyString();
    // 字符串构造函数
    MyString(const char*);
    // 复制构造函数
    MyString(const MyString& b);

    // 重载等号运算符
    MyString& operator=(const MyString &b);
    // 重载+=运算符
    MyString& operator+=(const MyString &b);
    // 重载比较运算符
    bool operator<(const MyString &b);
    // 重载下标运算符
    char& operator[](const int &index) const ;
    // 重载输入输出操作
    friend ostream& operator<<(ostream& ,const MyString &b);
    ~MyString();
};

MyString::MyString()
{
    str = new char[1];
    str[0]='\0';
    length = 0;
}

MyString::MyString(const char* b){
    if(b){
        length = strlen(b);
        str = new char[length+1];
        strcpy(str,b);
    }
    else{
        MyString();
    }
}
MyString::MyString(const MyString&b){
    length = b.size();
    if(length>0)
    str = new char[length+1];
    else
    MyString();
}

MyString& MyString::operator=(const MyString &b){
    if(&b == this){
        return *this;
    }
    delete[] str;
    length = b.size();
    str = new char[length + 1];
    strcpy(str,b.getstr());
    return *this;
}

MyString& MyString::operator+=(const MyString&b){
    if(b.size()==0){
        return *this;
    }
    char* temp = new char[length+b.length+1];
    strcpy(temp,str);
    strcat(temp,b.getstr());
    delete[] str;
    str = temp;
    return *this;
}

char& MyString::operator[](const int &index)const {
    if(index>length)return str[length];
    return str[index];
}

bool MyString::operator<(const MyString &b){
    for(int i=0;i<length;i++){
        if(i>b.size())return false;
        if(b[i]>str[i])return true;
        if(b[i]<str[i])return false;
    }
    return true;
}

MyString::~MyString()
{
    delete[] str;
}

// 外部定义一个函数,内部声明为友元
ostream& operator<<(ostream &out,const MyString&b){
    out<<b.getstr();
    return out;
}


int main()
{
    // 测试函数
    MyString s1,s2="123",s3,s4="456";
    s3=s2;
    s1=s2;
    s1+=s1;
    cout<<s1<<endl;
    cout<<s2<<endl;
    cout<<s3<<endl;
    cout<<(s3<s4)<<endl;
    cout<<endl;
    return 0;
}

5 实例——complex的实现

#include <iostream>
using namespace std;
class complex{
public:
    complex(double real = 0.0, double imag = 0.0): m_real(real), m_imag(imag){ };
public:
    friend complex operator+(const complex & A, const complex & B);
    friend complex operator-(const complex & A, const complex & B);
    friend complex operator*(const complex & A, const complex & B);
    friend complex operator/(const complex & A, const complex & B);
    friend istream & operator>>(istream & in, complex & A);
    friend ostream & operator<<(ostream & out, complex & A);
private:
    double m_real;  //实部
    double m_imag;  //虚部
};
//重载加法运算符
complex operator+(const complex & A, const complex &B){
    complex C;
    C.m_real = A.m_real + B.m_real;
    C.m_imag = A.m_imag + B.m_imag;
    return C;
}
//重载减法运算符
complex operator-(const complex & A, const complex &B){
    complex C;
    C.m_real = A.m_real - B.m_real;
    C.m_imag = A.m_imag - B.m_imag;
    return C;
}
//重载乘法运算符
complex operator*(const complex & A, const complex &B){
    complex C;
    C.m_real = A.m_real * B.m_real - A.m_imag * B.m_imag;
    C.m_imag = A.m_imag * B.m_real + A.m_real * B.m_imag;
    return C;
}
//重载除法运算符
complex operator/(const complex & A, const complex & B){
    complex C;
    double square = A.m_real * A.m_real + A.m_imag * A.m_imag;
    C.m_real = (A.m_real * B.m_real + A.m_imag * B.m_imag)/square;
    C.m_imag = (A.m_imag * B.m_real - A.m_real * B.m_imag)/square;
    return C;
}
//重载输入运算符
istream & operator>>(istream & in, complex & A){
    in >> A.m_real >> A.m_imag;
    return in;
}
//重载输出运算符
ostream & operator<<(ostream & out, complex & A){
    out << A.m_real <<" + "<< A.m_imag <<" i ";;
    return out;
}
int main(){
    complex c1, c2, c3;
    cin>>c1>>c2;
    c3 = c1 + c2;
    cout<<"c1 + c2 = "<<c3<<endl;
    c3 = c1 - c2;
    cout<<"c1 - c2 = "<<c3<<endl;
    c3 = c1 * c2;
    cout<<"c1 * c2 = "<<c3<<endl;
    c3 = c1 / c2;
    cout<<"c1 / c2 = "<<c3<<endl;
    return 0;
}

6 实例——MyTime的实现

//------mytime.h
#ifndef MYTIME_H
#define MYTIME_H
#include <iostream>
 
using namespace std;
 
class Time
{
	//----------私有成员,类中的成员默认是私有的
private:
	int hours;
	int mintues;
 
	//----------共有成员
public:
	Time();                                                       //默认构造函数
	Time(int h, int m = 0);                                       //显式构造函数
	Time(const Time &);                                           //拷贝构造函数
	~Time();                                                      //析构函数
	void AddMin(int m);
	void AddHour(int h);
 
	void reset(int h = 0, int m = 0);
 
	//------展示函数show()     
	void Time::show() const
	{
		cout << "hours:" << hours << "  " << "mintues:" << mintues << "  ";
	}
 
 
 
	Time operator+(const Time &t) const;                          //运算符重载
	
	Time operator-(const Time &t) const;
	Time operator*(double n) const;
	friend Time operator*(double n, const Time &t)                //友元;
	{
		return t*n;                                               //在这里又调用了重载运算符   operator*(double n) const;
	}                                                             //内联形式的定义;
 
 
 
	friend ostream & operator<<(ostream &os, const Time &t);     //一个双目运算符在重载时,如果是以友元的形式声明的,那么他有两个形参;如果是类的成员函数,那么他只有一个形参;
 
};
 
 
//-------时间重置,内联函数
inline void Time::reset(int h, int m)
{
	hours = h;
	mintues = m;
}

#endif


//--mytime.cpp
 
#include <iostream>
#include "mytime.h"
 
using namespace std;
 
//-------默认构造函数
Time::Time()
{
	hours = mintues = 0;
	cout << "调用默认构造函数" << endl;
}
 
//------显式的构造函数
Time::Time(int h, int m) :hours(h), mintues(m)
{
	cout << "调用显式构造函数" << endl;
}
 
//------拷贝构造函数
Time::Time(const Time &t)
{
	hours = t.hours;
	mintues = t.mintues;
	cout << "调用拷贝构造函数" << endl;
}
 
//------析构函数
Time::~Time()
{
	cout << "调用了析构函数" << endl;
}
 
//-------小时相加
void Time::AddHour(int h)
{
	hours += h;
}
 
//------分钟相加
void Time::AddMin(int m)
{
	mintues += m;
	hours += mintues / 60;
	mintues %= 60;
}
 
 
//------重载+号
Time Time::operator+(const Time &t) const
{
	Time sum;
	sum.mintues = mintues + t.mintues;
	sum.hours = hours + t.hours + sum.mintues / 60;
	sum.mintues = sum.mintues % 60;
	return sum;
}
 
//------重载-号
Time Time::operator-(const Time &t) const
{
	Time diff;
 
	int time1 = hours * 60 + mintues;
	int time2 = t.hours * 60 + t.mintues;
 
	diff.hours = (time1 - time2) / 60;
	diff.mintues = (time1 - time2) % 60;
 
	return diff;
}
 
//-------重载乘号
Time Time::operator*(double n) const
{
	Time result;
	long totalMintues = n*hours * 60 + n*mintues;
 
	result.hours = totalMintues / 60;
	result.mintues = totalMintues % 60;
 
	return result;
}
 
 
 
//-------友元输出操作符
ostream & operator<<(ostream &os, const Time &t)           //友元在类外定义的时候,不需要添加friend;
{
	os << "hours:" << t.hours << "  " << "mintues:" << t.mintues << "  ";
	return os;
}

//-----------------------
//main.cpp
//不用先生
//------------------------
#include <iostream>
#include "mytime.h"
 
using namespace std;
 
 
int main()
{
 
	{
		Time eat_breakfast(0, 45);
		Time eat_lunch(1, 0);
		Time eat_dinner(1, 30);
 
 
 
		Time swiming(0, 45);                   //非const对象,既可以调用const成员函数,也可以调用非const成员。
		const Time study(8, 5);                //const对象只能调用const成员函数。
 
 
		// study_cut_swim;
		Time study_cut_swim = study - swiming;      //调用运算符重载后的Time类的减号;
 
 
		Time Eat_time_day = eat_breakfast + eat_dinner + eat_lunch;    //调用了重载以后的加法;
 
		cout << "学习比游泳多花" << study_cut_swim << endl;           //调用友元输出运算符<<
		cout << "每周吃饭所花费的时间为" << (7 * Eat_time_day) << endl;  //调用了友元乘法以及输出运算符;
	}
 
 
 
	system("pause");
	return 0;
}

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

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

相关文章

vscode html使用less和快速获取标签less结构

扩展插件里面搜索 css tree 插件 下载 使用方法 选择你要生成的标签结构然后按CTRLshiftp 第一次需要在输入框输入 get 然后选择 Generate CSS tree less结构就出现在这个里面直接复制到自己的less文件里面就可以使用了 在html里面使用less 下载 Easy LESS 插件 自己创建…

深圳产品展示视频拍摄一站式服务

产品展示视频拍摄一站式服务是指一家专业的拍摄制作公司或团队提供从策划、拍摄到后期制作的全方位服务&#xff0c;以满足客户的产品展示需求。这种服务通常包括以下方面&#xff0c;由产品展示视频制作公司老友记小编从以下几个方面为您整理&#xff1a; 1.策划和预制阶段&a…

【期末复习笔记】计算机操作系统

计算机操作系统 进程的描述与控制程序执行进程进程的定义与特征相关概念定义特征进程与程序的区别 进程的基本状态和转换PCBPCB中的信息作用PCB的组织方式 线程进程与线程的比较 处理机调度与死锁处理机调度处理机调度的层次 调度算法处理机调度算法的目标处理机调度算法的共同…

PhpStorm安装篇

PhpStorm安装篇: 下载地址 : 进入官网下PhpStorm: PHP IDE and Code Editor from JetBrains 下载完之后&#xff0c;安装包 安装目录建议不要放C盘&#xff0c;放其他盘&#xff0c;其他直接一直点 next &#xff0c;到结束 安装完&#xff0c;打开编辑器 注册账号并登录后…

继续绷紧油市神经,市场预计沙特10月继续自愿减产

KlipC报道&#xff1a;据了解&#xff0c;市场参与者大都认为沙特阿拉伯将会把自愿额外减产的措施延长至10月底&#xff0c;以寻求在经济低迷的背景下提振油价。 KlipC的合伙人Andi D表示&#xff1a;“今年5月起&#xff0c;沙特就自愿减产日均50万桶原油&#xff0c;今年6月初…

苹果使用3D打印技术制造Apple Watch Series 9手表外壳

据彭博社的马克・古尔曼报道&#xff0c;苹果公司正在使用 3D 打印技术来制造即将推出的部分Apple Watch Series 9 的外壳。这种制造工艺可以节省传统数控加工所需的大量金属材料&#xff0c;同时缩短生产时间。这与之前苹果分析师郭明錤的说法相吻合。 苹果公司自2021年推出Ai…

Linux 虚拟机同步时间crontab以及crond详解

目录 一 Linux 虚拟机同步时间设置 1. 检查是否安装cron服务&#xff08;即时间同步器&#xff09; 2. 下载时间同步器 3. 编辑crontab 内容 4. 同步更新电脑网络时间 5.设置 reload 6. 查看 crond 状态 二 crond 详解 1. 启动/关闭cron服务 2. crontab命令格式 3. …

【LeetCode-中等题】138. 复制带随机指针的链表

文章目录 题目解题核心思路&#xff1a;找random指针指向思路一&#xff1a;哈希思路二&#xff1a;迭代构造新链表 方法一&#xff1a;哈希递归方法二&#xff1a;纯哈希方法三&#xff1a;迭代 节点拆分 题目 解题核心思路&#xff1a;找random指针指向 这里的拷贝属于深拷…

为什么曾经一马当先的C语言,如今却开始出现骂声

今日话题&#xff0c;为什么曾经一马当先的C语言&#xff0c;如今却开始出现各种骂声&#xff1f;C语言的发展历程可以追溯到20世纪70年代初期&#xff0c;它的设计理念、简洁性、可移植性以及对底层硬件的直接控制能力使其在计算机科学领域逐渐受到重视从而成为了天王搬到存在…

安捷伦DSA91204A高性能示波器/Agilent DSA91204A

描述 安捷伦的DSA90000A系列示波器为同等的DSO90000A产品增加了串行数据分析、EZJIT和50 M存储标准。 Infiniium DSO90000系列拥有业界领先的技术&#xff0c;能够提供超越规格的卓越示波器性能。加速测量任务的定制软件可以完全集成到示波器应用中&#xff0c;实现无缝操作。…

搭建Ubuntu本地web小游戏网站并通过内网穿透实现公网用户远程访问的步骤指南

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《高效编程技巧》《cpolar》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 前言1. 本地环境服务搭建2. 局域网测试访问3. 内网穿透3.1 ubuntu本地安装cpolar内网穿透3.2 创建隧道3.3 测试公网访…

大数据(六):Pandas的基础应用详解(三)

专栏介绍 结合自身经验和内部资料总结的Python教程&#xff0c;每天3-5章&#xff0c;最短1个月就能全方位的完成Python的学习并进行实战开发&#xff0c;学完了定能成为大佬&#xff01;加油吧&#xff01;卷起来&#xff01; 全部文章请访问专栏&#xff1a;《Python全栈教…

下岗吧,Excel

ChatGPT的诞生使Excel公式变得过时。通过使用 ChatGPT 的代码解释器你可以做到&#xff1a; 分析数据创建图表 这就像用自然语言与电子表格交谈一样。我将向大家展示如何使用 ChatGPT 执行此操作并将结果导出为Excel格式&#xff1a; 作为示例&#xff0c;我将分析并创建美国…

用最少数量的箭引爆气球【贪心算法】

用最少数量的箭引爆气球 有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points &#xff0c;其中points[i] [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。 一支弓箭可以沿着 x 轴从不同点 完全垂直 地…

JVM ZGC垃圾收集器

ZGC垃圾收集器 ZGC&#xff08;“Z”并非什么专业名词的缩写&#xff0c;这款收集器的名字就叫作Z Garbage Collector&#xff09;是一款在JDK 11中新加入的具有实验性质[1]的低延迟垃圾收集器&#xff0c;是由Oracle公司研发的。 ZGC收集器是一款基于Region内存布局的&#…

vue 入门案例模版

vue 入门案例1 01.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> &l…

如何用Python爬虫持续监控商品价格

目录 持续监控商品价格步骤 1. 选择合适的爬虫库&#xff1a; 2. 选择目标网站&#xff1a; 3. 编写爬虫代码&#xff1a; 4. 设定监控频率&#xff1a; 5. 存储和展示数据&#xff1a; 6. 设置报警机制&#xff1a; 7. 异常处理和稳定性考虑&#xff1a; 可能会遇到的…

HBuilderX修改manifest.json设置,解决跨域问题(CORS、Cross-Origin)

搭建一个前台uniapp&#xff0c;后台springboot的开发环境时&#xff0c;遇到了跨域问题。 console提示错误信息&#xff1a; Access to XMLHttpRequest at http://10.0.180.203/api/cms/getAdList?apId1 from origin http://localhost:8080 has been blocked by CORS policy…

【实战】十一、看板页面及任务组页面开发(六) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(二十八)

文章目录 一、项目起航&#xff1a;项目初始化与配置二、React 与 Hook 应用&#xff1a;实现项目列表三、TS 应用&#xff1a;JS神助攻 - 强类型四、JWT、用户认证与异步请求五、CSS 其实很简单 - 用 CSS-in-JS 添加样式六、用户体验优化 - 加载中和错误状态处理七、Hook&…

关于Echarts 绘制玫瑰图 (笔记)

目录 基于js文件绘图 基于vue3绘制玫瑰图 基于js文件绘图 // 定义一个配置对象 var option {// 图例设置legend: {top: bottom},// 工具栏设置toolbox: {show: true,feature: {mark: { show: true }, // 标记工具dataView: { show: true, readOnly: false }, // 数据视图工具r…