当前位置: 首页 > news >正文

C++之 友元重载 以及最常用的几种友元函数

在之前的友元中就曾经讲过,我们为了去访问修改私有成员中的数据时,只能通过公有的办法去进行访问操作,非常的局限。所以C++引用了友元函数,只要加上friend关键字,C++的这个类,会自动把这个函数的权限拉到类内,这样就可以访问私有成员了。

上一篇文章,讲了重载运算符的操作。但有些运算符不能够在类内进行重载,例如输入输出的符号。下面我会详细讲,为什么不能在类内进行重载。

这里我们先假设有一个类:

A{};//功能暂且不写,知道是个类就行了

首先,普通类内重载,会自带一个this指针,指向用此函数的对象。这被称作第一操作数。

如果在定义+号的时候,实际上是并不是简单的(类对象)+(某某)亦或是(某某)+(类对象);

它实际上全部的写法应该是:

A    a;                     //这里定义了一个对象a

a.operator+(某某);      //这是全部写法,也是正常情况应该写的情况,只是我们平时简写,编译器仍然认识罢了。

a+(某某)   // 这是我们平时的写法

比如你想重载<<或者>>符号,这种情况,他的第一操作符就一定不是类本身,例如:

A    a;

我们不可能写成:a<<或者是a>>;我们正常的写法应该是:cin >>a;cout << a;

这里第一操作符并不是a这个对象,而是cin/cout。这是ios的输入输出的参数。

这里有人就要问了,那(类对象)+(某某);我也可以写成(某某)+(类对象);这里实际上是交换律,因为,这里类对象写的地方,并不是唯一的,可以进行交换,这种情况可以不算。

话不多说,我们使用代码来进行讲解,下面先给大家展示时间类运算符重载,作为对比,我先写类内成员函数重载,再写类外友元重载,大家可以复制下来,看看。

#include <iostream>
#include <string>
using namespace std;/*
* 1.类的成员    在类内的运算符重载函数的第一个操作数一定是类的对象
* 总结:
*   有的情况运算符必须写成非成员函数.这个函数如果需要获得类对象的私有数据,则有如下方法
*   1.可以利用交换律(前提是类已经实现该运算符的重载.1.5*t->t*1.5)
*   2.类把该函数声明为它的友元函数
*   3.类提供获取私有数据的公有方法
*   
*   举例:如下  
*/
class Time
{
private:int hours;//小时int minutes;//分钟
public:Time(int h = 0, int m = 0) :hours(h), minutes(m)//构造函数{}Time operator +(const Time& t)const;//重载 +,注意返回值不是引用Time operator -(const Time& t)const//重载 -{int tmp = (hours * 60 + minutes) - (t.hours * 60 + t.minutes);//分钟return Time(tmp / 60, tmp % 60);}Time operator *(double n)const;//重载 *  .含义;3:40 * 3 ->11小时0分//3*3:40  不是void show() const;//提供获得时间的公有方法/* int GetHours()const{return hours;}int GetMinutes()const{return minutes;}*/
};Time Time::operator+(const Time& t)const  //2:30+2:45
{return Time(hours + t.hours + (minutes + t.minutes) / 60, (minutes + t.minutes) % 60);
}Time Time::operator *(double n)const  // Time * 小数
{double tmp = (hours * 60 + minutes) * n;return Time{ (int)tmp / 60,(int)tmp % 60 };
}void Time::show() const
{cout << hours << "小时," << minutes << "分钟" << endl;
}Time operator*(double n,const Time &t)//普通函数的形式重载*
{//double tmp = n * (t.hours * 60 + t.minutes);//错误,这个函数不是Time成员,不能访问它的私有// int tmp = (int)(n * (t.GetHours() * 60 + t.GetMinutes()));//  return Time(tmp/60,tmp%60);return t * n;//前提:已经实现了 t*n
}int main()
{Time t1{ 2,35 };Time t2 = { 2,40 };Time t3 = t1 + t2;//t1.operator+(t2);Time t4 = t2 - t1;//t2.operator-(t1);Time t5 = t1 * 1.5;Time t6 = 1.5 * t1;//没有实现 小数*时间t3.show();t4.show();t5.show();t6.show();//t1 * 3;//t1.operator*(3);//3*t1;//3.*(t1);//在3这个int类 没有实现对Time的*重载return 0;
}

接下来,作为对比,我继续把重载输入输出的代码。

#include <iostream>
#include <string>
using namespace std;class Time
{
private:int hours;//小时int minutes;//分钟public:Time(int h = 0, int m = 0);void show() const;//void operator <<(ostream& os)//os是输出流对象的引用//{//    os << hours << "小时,," << minutes << "分钟" << endl;//}friend Time operator *(double n, const Time& t);//这个是Time的友元函数friend ostream& operator <<(ostream& os, const Time& t);//这个是Time的友元函数//实现 >> 运算符重载   istreamfriend istream& operator >>(istream& is, Time& t);
};Time::Time(int h, int m)
{hours = h;minutes = m;
}void Time::show() const
{cout << hours << "小时," << minutes << "分钟" << endl;
}Time operator *(double n, const Time& t)
{int tmp = (int)(n * (t.hours * 60 + t.minutes));return Time(tmp/60,tmp%60);
}ostream & operator <<(ostream& os, const Time& t)//os不加const,需要把数据写入到输出流
{os << t.hours << "小时,," << t.minutes << "分钟" << endl;return os;
}istream& operator >>(istream& is, Time& t)
{return is >> t.hours >> t.minutes;
}int main()
{Time t1 = { 2,35 };Time t2 = { 2,40 };Time t3 = 1.5*t1;  //第一个操作数不是类对象,所以只能是非成员函数//t3.show();//t3 << cout; //可以作为类成员函数的,但不能理解cout << t3;//这个不能调用t3的成员函数,但我们需要cout << t1 << t2;cin >> t1; //5 30cout << t1;//5小时,30分钟// cout << t3 ;//错误,没有实现如何 cout<< Time的对象//cout 是 ostream类对象  ; cin是istream类对象return 0;
}

每日金句:

        一步一行,便无惧陷入泥沼!

                                                                                                           ---------------银枝

相关文章:

C++之 友元重载 以及最常用的几种友元函数

在之前的友元中就曾经讲过&#xff0c;我们为了去访问修改私有成员中的数据时&#xff0c;只能通过公有的办法去进行访问操作&#xff0c;非常的局限。所以C引用了友元函数&#xff0c;只要加上friend关键字&#xff0c;C的这个类&#xff0c;会自动把这个函数的权限拉到类内&a…...

动态规划(3)——dp多状态问题Ⅰ

题一.按摩师&#xff08;LeetCode&#xff09; 题目描述 一个有名的按摩师会收到源源不断的预约请求&#xff0c;每个预约都可以选择接或不接。在每次预约服务之间要有休息时间&#xff0c;因此她不能接受相邻的预约。给定一个预约请求序列&#xff0c;替按摩师找到最优的预约集…...

在Mac电脑上安装adb环境

当你在命令行输入 adb version 或adb devices, 报错&#xff1a;zsh: command not found: adb &#xff0c;那么说明你的 Mac 上没有安装 ADB&#xff08;Android Debug Bridge&#xff09;&#xff0c;或者它没有添加到你的路径中。你可以按照以下步骤安装和配置 ADB&#xff…...

分糖果C++

题目&#xff1a; 样例解释&#xff1a; 样例1解释 拿 k20 块糖放入篮子里。 篮子里现在糖果数 20≥n7&#xff0c;因此所有小朋友获得一块糖&#xff1b; 篮子里现在糖果数变成 13≥n7&#xff0c;因此所有小朋友获得一块糖&#xff1b; 篮子里现在糖果数变成 6<n7&#xf…...

Spring中如何为静态变量注入值

在 Spring 中&#xff0c;如果使用 Value 注解注入值&#xff0c;不能将其应用于 static 字段。Spring 只能为实例变量注入值&#xff0c;不能直接对静态变量进行注入。 使用 PostConstruct 初始化&#xff1a; 如果确实需要在静态上下文中使用该值&#xff0c;可以使用 Post…...

HTML5实现唐朝服饰网站模板源码

文章目录 1.设计来源1.1 网站首页-界面效果1.2 唐装演变-界面效果1.3 唐装配色-界面效果1.4 唐装花纹-界面效果1.5 唐装文化-界面效果 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xcL…...

ESXI识别USB设备

步骤&#xff1a; 插入usb设备到服务器。关闭虚拟机&#xff0c;添加USB控制器&#xff0c;根据U盘选择usb 3.0控制器&#xff0c;再添加usb设备如果usb设备灰色&#xff0c;进入主机打开SSH。使用xshell进行连接&#xff0c;运行以下命令&#xff1a; ESXI识别USB设备 - 插入…...

视频美颜SDK与直播美颜工具API是什么?计算机视觉技术详解

今天&#xff0c;小编将深入探讨视频美颜SDK与直播美颜工具API的概念及其背后的计算机视觉技术。 一、视频美颜SDK的概念 视频美颜SDK是一套用于开发实时美颜效果的工具集&#xff0c;开发者可以利用它在视频流中实现面部特征的优化。这些SDK通常提供了一系列功能&#xff0c…...

not exist 解决一对多 场景 条件过滤问题

场景&#xff1a; 现在存在一对多关系&#xff0c;蓝色的盒子装的篮球&#xff0c;黄的的盒子装的黄球&#xff0c; 黑色的盒子 &#xff08;模拟工作类似场景&#xff09; boxIdballId蓝盒ID-15蓝盒ID-16蓝盒ID-17黄盒ID-212黄盒ID-215黄盒ID-216黑盒ID-38黑盒ID-39 需求&a…...

解决$‘r‘ command not found或者文件夹显示’tvsf 33‘$‘r‘

问题现象: 某客户反馈在执行脚本的时候文件夹显示存在问题,如下图: 但是脚本文件中的内容并没有\r字符,如下图: 也有客户反馈如下: 问题分析: $\r’是回车符的转义表示。在Unix和Linux系统中,回车符是一个不可见的控制字符,它通常用于文本文件中的行结尾。以上…...

linux:详解nohup命令

在 UNIX 和类 UNIX 操作系统&#xff08;如 Linux 和 macOS&#xff09;中&#xff0c;nohup 意图为后台运行且免疫挂断信号的命令&#xff0c;用于在用户注销&#xff08;logout&#xff09;或终端关闭后继续运行相应的进程。 基本语法 启动进程 nohup [COMMAND] [ARG...] …...

负载箱:充电桩测试利器

RCD负载箱是用于测试和验证电气设备在故障状态下的性能的设备。它可以模拟真实的负载情况&#xff0c;从而帮助工程师和技术人员对设备进行准确的检测和维护。此外&#xff0c;RCD负载箱也是一种重要的安全保护设备&#xff0c;主要用于防止电路中的漏电现象引发的事故。它通常…...

Ubuntu 开机自启动 .py / .sh 脚本,可通过脚本启动 roslaunch/roscore等

前言 项目中要求上电自启动定位程序&#xff0c;所以摸索了一种 Ubuntu 系统下开机自启动的方法&#xff0c;开机自启动 .sh 脚本&#xff0c;加载 ROS 环境的同时启动 .py 脚本。在 . py 脚本中启动一系列 ROS 节点。 一、 .sh 脚本的编写 #!/bin/bash # gnome-terminal -- …...

RabbitMQ 消息队列:生产者与消费者实现详解

在分布式系统中&#xff0c;消息队列&#xff08;Message Queue, MQ&#xff09;是一种重要的组件&#xff0c;用于解耦系统、异步处理任务以及实现系统间的通信。RabbitMQ 是一个流行的开源消息代理软件&#xff0c;它实现了高级消息队列协议&#xff08;AMQP&#xff09;。在…...

vue3项目中组件切换不起作用

以下这种方式写页面中组件切换&#xff0c;不起作用。 <component :is"steps[compIndex].comp" />解决&#xff1a;使用shallowReactive或者shallowRef把对应的组件名称重新定义下。 <component :is"compNames[steps[compIndex].comp]" /> &…...

YOLOv11改进策略【损失函数篇】| Slide Loss,解决简单样本和困难样本之间的不平衡问题

一、本文介绍 本文记录的是改进YOLOv11的损失函数&#xff0c;将其替换成Slide Loss&#xff0c;并详细说明了优化原因&#xff0c;注意事项等。Slide Loss函数可以有效地解决样本不平衡问题&#xff0c;为困难样本赋予更高的权重&#xff0c;使模型在训练过程中更加关注困难样…...

动静态库(Linux)

文章目录 前言一、静态库二、动态库三、深入理解动态库总结 前言 我们之前用过c语言的库.Linux中默认的都是使用动态库&#xff0c;如果想要使用静态库&#xff0c;就必须加上-static选项。默认都是安装的动态库&#xff0c;系统中一般没有静态库&#xff0c;如果要使用&#…...

51单片机和ARM单片机的区别

在嵌入式系统设计与应用中&#xff0c;单片机作为核心控制单元&#xff0c;扮演着至关重要的角色。其中&#xff0c;51单片机和ARM单片机作为两种常见的单片机类型&#xff0c;各自具有独特的特点和优势。本文将从多个维度深入探讨这两种单片机的区别&#xff0c;以便读者更好地…...

[Day 81] 區塊鏈與人工智能的聯動應用:理論、技術與實踐

區塊鏈在食品安全中的應用 前言 食品安全一直是全球關注的問題&#xff0c;隨著全球供應鏈的複雜性增加&#xff0c;追踪食品從生產到消費的過程變得愈發困難。區塊鏈技術以其去中心化、不可篡改的特性&#xff0c;為食品安全提供了可靠的解決方案。在這篇文章中&#xff0c;…...

flac格式怎么转mp3?关于flac转为MP3的方法介绍

flac格式怎么转mp3&#xff1f;MP3格式经过压缩&#xff0c;相较于flac文件&#xff0c;显著减小了文件体积。这一特点使得音乐的存储和传输更加便捷&#xff0c;尤其适合移动设备以及存储空间有限的场景。由于MP3文件体积较小&#xff0c;分享音乐变得非常简单&#xff0c;无论…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist

现象&#xff1a; android studio报错&#xff1a; [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决&#xff1a; 不要动CMakeLists.…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解

进来是需要留言的&#xff0c;先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码&#xff0c;输入的<>当成字符串处理回显到页面中&#xff0c;看来只是把用户输…...

第八部分:阶段项目 6:构建 React 前端应用

现在&#xff0c;是时候将你学到的 React 基础知识付诸实践&#xff0c;构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段&#xff0c;你可以先使用模拟数据&#xff0c;或者如果你的后端 API&#xff08;阶段项目 5&#xff09;已经搭建好&#xff0c;可以直接连…...