第十一章——使用类

news2024/12/24 0:25:18

运算符重载

 运算符重载是一种形式的C++多态。之前介绍过的函数重载(定义多个名称相同但特征标不同的函数)让程序员能够用同名的函数来完成相同的基本操作,即使这些操作被用于不同的数据类型。

运算符重载将重载的概念扩展到运算符上,允许赋予C++运算符多种含义。(比如将*运算符用于地址,将得到存储在这个地址中的值,但将它用于两个数字时,得到的是它们的乘积)。C++根据操作数的数目和类型来决定采用哪种操作

C++允许将运算符重载扩展到用户定义的类型。

要重载运算符,需使用被称为运算符函数的特殊函数形式,格式如下:

operator op(argument-list)

 例如,operator +()重载+运算符,operator *()重载*运算符。op必须是一个有效的C++运算符,不能虚构一个新的符号

计算时间:一个运算符重载示例

 如果在Priggs的账户上花费了2小时35分钟,下午又花费了2小时40分钟,则总共花了多少时间呢?这个与加法概念相似,但要相加的单位(小时与分钟的混合)与内置类型不匹配。

首先我们先使用常规方法,然后介绍如何将其转换为重载运算符

mytime0.h

#ifndef MYTIME0_H_
#define MYTIME0_H_

class Time
{
private:
	int hours;
	int minutes;
public:
	Time();
	Time(int h, int m = 0);
	void AddMin(int m);
	void AddHr(int h);
	void Reset(int h = 0, int m = 0);
	Time sum(const Time& t) const;
	void Show()const;
};
#endif

Time类提供了用于调整和重新设置时间、显示时间、将两个时间相加的方法

mytime0.cpp

#include<iostream>
#include"mytime0.h"
Time::Time()
{
	hours = minutes = 0;
}
Time::Time(int h, int m )
{
	hours = h;
	minutes = m;
}
void Time::AddMin(int m)
{
	minutes += m;
	hours += minutes / 60;
	minutes %= 60;
}
void Time::AddHr(int h)
{
	hours += h;
}
void Time::Reset(int h, int m )
{
	hours = h;
	minutes = m;
}
Time Time::sum(const Time& t)const
{
	Time sum;
	sum.minutes = minutes + t.minutes;
	sum.hours = hours + t.hours + sum.minutes / 60;
	sum.minutes %= 60;
	return sum;
}
void Time::Show()const
{
	std::cout << hours << " hours, " << minutes << " minutes";
}

不要返回指向局部变量或临时对象的引用。函数执行完毕后,局部变量和临时对象将消失,引用将指向不存在的数据

usetime0.cpp

#include<iostream>
#include"mytime0.h"
int main()
{
	using std::cout;
	using std::endl;
	Time planning;
	Time coding(2, 40);
	Time fixing(5, 55);
	Time total;

	cout << "planning time = ";
	planning.Show();
	cout << endl;

	cout << "coding time = ";
	coding.Show();
	cout << endl;

	cout << "fixing time = ";
	fixing.Show();
	cout << endl;

	total = coding.sum(fixing);
	cout << "coding.Sum(fixing) = ";
	total.Show();
	cout << endl;

	return 0;
}

 程序最终的输出是

 添加 加法运算符

将Time类转换为重载的加法运算符很容易,只要将sum()的名称改为operator +()即可。 

像sum()一样,operator +()也是由Time对象调用的,它将第二个Time对象作为参数,并返回一个Time对象,因此可以像调用sum()那样来调用operator +()方法

total = coding.operator +(fixing);

也可以使用运算符表示法:

total = coding + fixing

这两种表示法都将调用operator +()方法。在运算符表示法中,运算符左侧的对象(这里为coding)是调用对象,运算符右边的对象(这里是fixing)是作为参数被传递的对象

operator +()函数的名称使得可以使用函数表示法或者运算符表示法来调用它。编译器将根据操作数的类型来决定如何做:

int a,b,c;
Time A,B,C;
c = a + b;    //use int addition
C = A + B;    //use addtion as defined for Time objects

 重载限制

多数C++运算符都可以用这样的方式重载,重载的运算符不必是成员函数,但必须至少有一个操作数是用户定义的类型

1.重载后的运算符必须至少有一个操作数是用户定义的类型,这将防止用户为标准类型重载运算符

2.使用运算符时不能违反运算符原来的句法规则(例如不能将%运算符重载成使用一个操作数),同样也不能修改运算符的优先级

3.不能创建新运算符

4.不能重载下面的运算符

  • sizeof:sizeof运算符
  • . :成员运算符
  • .* :成员指针运算符
  • :: :作用域解析运算符
  • ? : :条件运算符
  • typeid:一个RTTI运算符
  • const_cast:强制类型转换运算符
  • dynamic_cast:强制类型转换运算符
  • reinterpret_cast:强制类型转换运算符
  • static_cast:强制类型转换运算符

表中的大多数运算符都可以通过成员或非成员函数进行重载,但 下面的运算符只能通过成员函数进行重载

  • =,赋值运算符
  • (),函数调用运算符
  • [ ],下标运算符
  • ->,通过指针访问类成员的运算符

 

友元 

C++控制对类对象私有部分的访问。通常共有类方法提供唯一的访问途径,但是有时候这种限制太严格,C++提供了另外一种形式的访问 

 友元有3种

 友元函数;友元类;友元成员函数;

 通过让函数成为类的友元,可以赋予该函数与类的成员函数相同的访问权限,这里先介绍友元函数

创建友元

 创建友元函数的第一步是将其原型放在类声明中,并在原型声明前加上关键字friend:

friend Time operator*(double m, const Time & t);

该原型意味着:

  • 虽然operator*()函数是在类声明中声名的,但它不是成员函数,因此不能使用成员运算符来调用
  • 虽然operator*()函数不是成员函数,但它与成员函数的访问权限相同

第二步是编写函数定义。因为它不是成员函数,所以不要使用Time::限定符,另外不要在定义中使用关键字friend,定义如下:

Time operator*(double m ,const Time & t)
{
    Time result;
    long totalminutes = t.hours * m * 60 + t.minutes *m;
    result.hours = totalminutes / 60;
    result.minutes = totalminutes % 60;
    return result;
}

总之类的友元函数是非成员函数,其访问权限与成员函数相同。

 常用的友元:重载<<运算符

可对<<运算符进行重载,使之能与cout一起来显示对象的内容

1.<<的第一种重载版本

要是Time类知道使用cout,必须使用友元函数。因为下面这样的语句使用两个对象,其中第一个是ostream类对象(cout):

cout<<trip;

 如果使用一个Time成员函数来重载<<,Time对象将是第一个操作数,则必须这样使用<<:

trip<<cout;

看起来很奇怪

但通过使用友元函数,可以像下面这样重载运算符

void operator<<(ostream &os, const Time &t)
{
    os<<t.hours<<"hours,"<<t.minutes<<"minutes";
}

这样就可以使用下面看起来正常的语句

cout<<trip;

新的Time类声明使operator<<()函数称为Time类的一个友元函数,但该函数不是ostream类的友元

2.<<的第二种重载版本

前面介绍的实现存在一个问题,像下面这样的语句可以正常工作

cout<<trip;

但不允许像通常的cout与<<那样

cout<<"Trip time: "<<trip<<"Tuesday";    //can't do it

所以对operator<<()函数进行修改,让它返回ostream对象的引用即可:

ostream & operator<<(ostream & os, const Time &t)
{
    os<<t.hours<<"hours,"<<t.minutes<<"minutes";
    return os;
}

注意返回类型是ostream&,即该函数返回ostream对象的引用

一般来说,要重载<<运算符来显示c_name的对象,可使用一个友元函数,其定义如下 :

ostream & operator<<(ostream & os, const c_name &obj)
{
    os<<...;
    return os;
}

 重载运算符:作为成员函数还是非成员函数

对于很多运算符来说,可以选择使用成员函数或非成员函数来实现运算符重载。

例如重载+运算符需要两个操作数。对于成员函数版本来说,一个操作数通过this指针隐式地传递,另一个操作数作为函数参数显式地传递;对于友元函数版本来说,两个操作数都作为参数来传递

非成员函数重载”+“

Num operator+(const Num &m1,const Num &m2)
{
    Num temp;
    temp.n = m1.n + m2.n;
    return temp;
}

成员函数重载”+“

Num Num::operator +(const Num &t)
{
    Num temp;
    temp.n = n + t.n;
    return temp;
}

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

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

相关文章

gulimall-性能监控与压力测试

性能监控与压力测试 前言一、性能监控1.1 jvm 内存模型1.2 jvisualvm 作用1.3 监控指标 二、压力测试2.1 概念2.2 性能指标2.3 JMeter 压测工具 前言 本文继续记录B站谷粒商城项目视频 P141-150 的内容&#xff0c;做到知识点的梳理和总结的作用。 一、性能监控 1.1 jvm 内存…

灯具小程序怎么制作

灯具小程序怎么制作&#xff0c;有什么功能 1. 商品展示&#xff1a;灯具小程序商城提供了丰富多样的灯具产品&#xff0c;并通过清晰的商品展示页面展示给用户。用户可以浏览不同种类的灯具&#xff0c;包括吊灯、台灯、壁灯等&#xff0c;了解产品的图片、规格、价格等详细信…

python 文件夹py文件相互引用

文章目录 前言Python文件相互调用情况一&#xff1a;同级文件情况二&#xff1a;非同级文件上层调用下层下层调用上层sys.path.append(.)详细测试同名测试引入结论 跨文件夹调用 总结 前言 我之前学过一些别的语言&#xff0c;例如Java,C#,JS。所以我上手python还是挺快的&…

Threejs模型切片转3DTiles加载

个人主页&#xff1a; 左本Web3D&#xff0c;更多案例预览请点击》 在线案例 个人简介&#xff1a;专注Web3D使用ThreeJS实现3D效果技巧和学习案例 &#x1f495; &#x1f495;积跬步以至千里&#xff0c;致敬每个爱学习的你。获取模型或源码请点赞收藏加留言&#xff0c;有问…

Scala中的集合

水善利万物而不争&#xff0c;处众人之所恶&#xff0c;故几于道&#x1f4a6; 目录 一、集合简介 二、集合关系继承图 一、集合简介 Java中的集合&#xff1a; Scala中的集合&#xff1a; Scala的集合有三大类&#xff1a;序列Seq、集Set、映射Map&#xff0c;所有的集合…

Vue3+Vite+Pinia+Naive后台管理系统搭建之七:utils 工具构建

前言 如果对 vue3 的语法不熟悉的&#xff0c;可以移步Vue3.0 基础入门&#xff0c;快速入门。 1. cookie 保存工具 1.1 安装依赖 yarn add js-cookie // or npm install js-cookie 1.2 编写 src/utils/cookie.js // src/utils/cookie.js import Cookies from "js-co…

操作系统_计算机系统

目录 1. 操作系统的基本概念 1.1 操作系统的特征 1.1.1 并发&#xff08;Concurrence&#xff09; 1.1.2 共享&#xff08;Sharing&#xff09; 1.1.3 虚拟&#xff08;Virtual&#xff09; 1.1.4 异步&#xff08;Asynchronism&#xff09; 1.2 操作系统的目标和功能 …

FIR滤波器与IIR滤波器的区别与特点

目录 FIR滤波器与IIR滤波器的区别与特点 FIR滤波器定义&#xff1a; 特点&#xff1a; IIR滤波器定义&#xff1a; 特点&#xff1a; 区别&#xff1a; IIR滤波器有以下几个特点&#xff1a; IIR与FIR数字滤波器的比较&#xff1a; 1、从性能上比较 2、从结…

Firewalld防火墙 图形和字符

目录 字符界面 一、防火墙介绍 二、防火墙的基本应用 将防火墙接口划分到区域中 区域添加访问规则 图形界面 字符界面 安装图形化防火墙管理工具 [rootbogon ~]# yum -y install firewall-config 一、防火墙介绍 1、netfilter和防火墙管理工具 1&#xff09;netfilter …

Unity Obfuscator 过滤指定目录下的所有类

视频 Unity Obfuscator 过滤指定目录下的所有class 源码 替换调 OptionsManager 脚本文件就可以了 using System.Collections.Generic; using UnityEngine; using UnityEditor;

Tomcat查看源码

比如需要从请求域拿数据 点击右上角的Choose Sources 找到对应源码的位置 源码 下载Tomcat源码 http://tomcat.apache.org 下载指定版本Tomcat https://archive.apache.org/dist/tomcat/ 下载下来解压即可

spring boot MySQL操作

极简spring boot MySQL测试 默认: spring boot环境已经搭好,可以跑最基本的hello world 有MySQL环境有部分测试数据表,并且有MySQL语法基础 配置 application.yml 如下配置,根据自己的数据库信息与个人需求配置 server: tomcat: uri-encoding: UTF-8 threads: …

为什么TCP是面向字节流协议

大家好&#xff0c;我是三叔&#xff0c;很高兴这期又和大家见面了&#xff0c;一个奋斗在互联网的打工人。 笔者在TCP 机制一文中有说到 TCP 是面向字节流的&#xff0c;这篇博客给大家介绍一下&#xff1a;为什么 TCP 是面向字节流协议的。 首先说一下 UDP &#xff0c;是一…

prompt:有需求就有价值,prompt案例

prompt&#xff1a;有需求就有价值 此文章来自于小七姐 首先来看需求&#xff1a; 客户需要生成1000条俏皮灵动&#xff0c;趣味盎然&#xff0c;比喻精妙的和美食有关的短句子&#xff0c;要求文风优美&#xff0c;句子让人充满食欲。 客户使用这些句子的场景比较奇妙&…

eval() trim() dispaly:contents等属性的理解

1.eval(除去前后的双引号) 2.字符串.trim() 除去前后的空格 3.display:contents(提升到父级元素的子集元素)

How to Make Your Writing Stand Out From AI 如何让你的写作从人工智能中脱颖而出

Thanks to amazing tools such as ChatGPT, there is now a flood of well-written, functional, and useful writing to compete with if you’re a human writer. This means your writing needs to differentiate itself from this new breed of content. Here’s how to do…

OSError [Errno 22] Invalid argument(已解决)

最近跑别人的项目遇到一个这样的问题 OSError: [Errno 22] Invalid argument xxxxxxxxxxxxxxxxxx一开始以为是没有用管理员的权限运行&#xff0c;导致创建不了日志文件 后来发现是和windows的命名规则冲突了&#xff08;以下来源官网地址&#xff09; 命名约定 以下基本规…

希尔排序法解析

希尔排序法解析 什么是希尔排序法 希尔排序法&#xff08;Shell Sort&#xff09;&#xff0c;也称为缩小增量排序&#xff0c;是一种改进的插入排序算法。它通过将待排序的元素按照一定的间隔分组&#xff0c;对每个分组进行插入排序&#xff0c;逐渐减小间隔直至为1&#x…

单个电源模块不带电感的直流压降仿真

单个电源模块不带电感的直流压降仿真 前面讲过POWER DC如何对单个电源模块带电感的直流压降仿真,下面介绍如何对单个电源模块不带电感的直流压降仿真,以下图为例

启动优化中的一些黑科技,了解一下~

1前言 启动速度优化是 android 开发中的常见需求&#xff0c;除了一些常规的手段之外&#xff0c;也有一些黑科技手段&#xff0c;我们来看一下这些黑科技手段是否有效&#xff0c;以及如何实现 本文主要是对Android 性能优化小册相关内容的学习实践&#xff0c;加入了自己的…