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

news2024/11/29 1:32:50

运算符重载的两种方式

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;
}

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

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

相关文章

可控硅调功电路原理

在常见的马达调速以及需要调整负载功率的场合&#xff0c;经常会用到可控硅调功电路&#xff0c;下图是常见的应用电路。 调功电路主要由阻容移相电路和可控硅触发电路构成&#xff0c;工作过程如下&#xff0c;当交流电的正半周时&#xff0c;交流电通过R5,可调电阻R3给电容C1…

Elasticsearch数据库操作

索引操作 新建索引 PUT /ztt {"mappings": {"properties": {"info":{"type": "text","analyzer": "ik_smart"},"email":{"type": "keyword","index": false…

简单聊聊Https的来龙去脉

简单聊聊Https的来龙去脉 Http 通信具有哪些风险Https Http SSL/TLS对称加密 和 非对称加密数字证书数字证书的申请数字证书怎么起作用 Https工作流程一定需要Https吗&#xff1f; Http 通信具有哪些风险 使用明文通信&#xff0c;通信内容可能会被监听不验证通信双方身份&a…

每天刷题五道RHCSA/6-10题(Radhat8.2)

6.创建协作目录权限 mkdir /home/managers chown :sysmgrs /home/managers chmod 2770 /home/managers 测试&#xff1a; touch /home/managers/12345 ll /home/managers/12345 7.配置NTP systemctl status chronyd #查看状态 yum -y install chrony #如果没有安装&#xff0c…

最佳实践:TiDB 业务读变慢分析处理

作者&#xff1a;李文杰 网易游戏计费 TiDB 负责人 在使用或运维管理 TiDB 的过程中&#xff0c;大家几乎都遇到过 SQL 变慢的问题&#xff0c;尤其是查询相关的读变慢问题。读变慢的问题大部分情况下都遵循一定的规律&#xff0c;通过经验的积累可以快速的定位和优化&#xff…

Java实现根据关键词搜索京东商品列表数据方法,当当API接口(jd.item_search)申请指南

要通过京东网的API获取商品列表数据&#xff0c;您可以使用京东开放平台提供的接口来实现。以下是一种使用Java编程语言实现的示例&#xff0c;展示如何通过京东开放平台API获取商品列表&#xff1a; 首先&#xff0c;确保您已注册成为当当开放平台的开发者&#xff0c;并创建…

五金轴尺寸机器视觉测量软硬件方案--康耐德智能

检测内容&#xff1a; 五金轴尺寸机器视觉测量 检测要求&#xff1a; 精度0.015mm&#xff0c;速度180~240个/分钟 视觉可行性分析&#xff1a; 对样品进行了光学实验&#xff0c;并进行图像处理&#xff0c;原则上可以使用机器视觉系统进行测试测量。 结果&#xff1a; 对…

新手小白想要做好跨境电商独立站,需要考虑哪些要素?

对于不少中小卖家而言&#xff0c;利用独立站出海已然成为下一个跨境热潮。但是采用独立站模式做出海生意前&#xff0c;卖家需要考虑哪些要素&#xff1f; 产品选择 对于国内的卖家来说&#xff0c;依托于国内强大的供应链优势&#xff0c;只要能把握住消费者心态&#xff0…

C# 获取Windows系统版本注意事项

首先通过微软官方文档&#xff1a;https://learn.microsoft.com/zh-cn/windows/win32/sysinfo/operating-system-version了解各个操作系统对应的版本号 下面介绍3种获取版本号的方式及弊端 1. Environment.OSVersion.Version OperatingSystem os Environment.OSVersion;// 判断…

Dapper入门教程

什么是Dapper Dapper是一个简单的.NET对象映射器&#xff0c;在速度方面具有"King of Micro ORM"的头衔&#xff0c;几乎与使用原始的ADO.NET数据读取器一样快。ORM是一个对象关系映射器&#xff0c;它负责数据库和编程语言之间的映射。 Dapper通过扩展IDbConnecti…

PSP - 蛋白质结构预测 OpenFold Multimer 模型训练参数与配置

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132575709 OpenFold Multimer 是用于预测蛋白质多聚体结构的计算方法。基于OpenFold 的单体预测框架&#xff0c;利用深度学习技术&#xff0c;结…

指针与空间按钮的交互

文章目录 原理案例&#xff1a;“直线指针”和“点击按钮”的交互1、效果2、步骤 原理 指针不能直接和空间按钮交互&#xff0c;得借助一个中间层——分发器——它分发指针的进入、退出、选择事件&#xff0c;空间按钮自动监听这些事件 案例&#xff1a;“直线指针”和“点击…

SQLServer审计功能配置

一. SQL Server审计功能介绍 SQL Server审计功能&#xff08;Audit&#xff09;是SQL Server 2008之后才有的功能&#xff0c;审计(Audit)用于追踪和记录SQL Server实例&#xff0c;或者单个数据库中发生的事件(Event)&#xff0c;审计运作的机制是通过捕获事件(Event)&#x…

Vector 动态数组(迭代器)

C数据结构与算法 目录 本文前驱课程 1 C自学精简教程 目录(必读) 2 Vector<T> 动态数组&#xff08;模板语法&#xff09; 本文目标 1 熟悉迭代器设计模式&#xff1b; 2 实现数组的迭代器&#xff1b; 3 基于迭代器的容器遍历&#xff1b; 迭代器语法介绍 对迭…

3分钟上手Python的命令行参数解析

1 简介 处理命令行参数对许多程序来说都是必不可少的功能。今天为大家介绍 Python 中的 argparse 模块&#xff0c;它是 Python 标准库中的一个模块&#xff0c;它可以让开发者非常简单地为程序添加命令行参数接口&#xff0c;包括位置参数、可选参数、标志等&#xff0c;并自…

测试左移——代码审计SonarQube 平台搭建

一、sonarqube代码分析技术体系 1、代码分析工具 IDE 辅助功能 xcode、android studio阿里巴巴 java 开发手册 ide 插件支持 独立的静态分析工具 spotbugs、findbugs、androidlint、scan-build、Checkstyle、FindSecBugspmd 阿里巴巴 java 开发手册 pmd 插件 综合性的代码…

说说FLINK细粒度滑动窗口如何处理

分析&回答 Flink的窗口机制是其底层核心之一&#xff0c;也是高效流处理的关键。Flink窗口分配的基类是WindowAssigner抽象类&#xff0c;下面的类图示出了Flink能够提供的所有窗口类型。 Flink窗口分为滚动&#xff08;tumbling&#xff09;、滑动&#xff08;sliding&am…

DWA算法学习

一、DWA概念  DWA(动态窗口法)属于局部路径规划方法&#xff0c;为ROS中主要采用的方法。其原理主要是在速度空间&#xff08;v,w&#xff09;中采样多组速度&#xff0c;并模拟这些速度在一定时间内的运动轨迹&#xff0c;再通过一个评价函数对这些轨迹打分&#xff0c;最优的…

2023年全国职业院校技能大赛网络系统管理赛项 模块B:服务部署 卷II

2023年全国职业院校技能大赛 GZ073网络系统管理赛项 模块B&#xff1a;服务部署 卷II 目 录 一、Windows项目任务描述 1 &#xff08;一&#xff09;拓扑图 1 &#xff08;二&#xff09;网络地址规划 1 二、Windows项目任务清单 2 &#xff08;一&#xff09;服务器IspSrver…

数据库(一) 基础知识

概述 数据库是按照数据结构来组织,存储和管理数据的仓库 数据模型 数据库系统的核心和基础是数据模型&#xff0c;数据模型是严格定义的一组概念的集合。因此数据模型一般由数据结构、数据操作和完整性约束三部分组成。数据模型主要分为三种:层次模型&#xff0c;网状模型和关…