c++入门学习⑥——友元和运算符重载

目录

简介:

友元:

全局函数做友元

类做友元

成员函数做友元

运算符重载

加号运算符重载

代码示例:

输入输出运算符重载

⭐cin

⭐cout

代码示例:

分析:

自增运算符重载

代码示例(成员函数实现):

分析:

==运算符重载

代码示例:

分析:

函数调用运算符()重载

代码示例:

以上的运算符完整重载代码:

总结:


简介:

介绍有关友元和运算符重载的知识,运算符重载根据介绍

友元:

1.类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。

⭐注意:友元函数并不是成员函数👉尽管友元函数的原型有在类的定义中出现了。

2.友元可以是一个函数,该函数被称为友元函数友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。

3.如果要声明函数为一个类的友元,需要在类定义中该函数原型前使用关键字 friend

全局函数做友元

#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std; 
//友元,有些私有的属性想要类外的某些函数或者是类来访问,就需要友元
//friend
//实现三种:全局函数做友元
class building {//建筑物类
    friend void test(building& build);//实现全局函数可以访问私有成员了
public:
    building() {
        m_sittingroom = "客厅";
        m_bedroom = "卧室";
    }
public:
    string m_sittingroom;
private:
    string m_bedroom;
};
//引用或者指针传入
 void test(building &build)//全局函数,可以访问私有成员
{
     cout << "访问公共属性" << build.m_sittingroom<<endl;//运行成功
     cout << "访问私有属性" << build.m_bedroom << endl;//加上类中的第一行代码之后就可以正常运行了
}
 void test1() {
     building build;
    test(build);
 }
int main()
{
    test1();
    system("pause");
    return 0;
}

类做友元

#include<iostream>
#include<string>
using namespace std; 
//友元,有些私有的属性想要类外的某些函数或者是类来访问,就需要友元
//friend为关键字
//实现:类做友元,类可以访问另一个类的私有属性

class building {//建筑物类
    //good friend是本类的好朋友,
    friend class goodfriend;
public:
    building();
    string m_sittingroom;
private:
    string m_bedroom;
};

building::building() {//构造函数赋初值
    m_sittingroom = "客厅";
    m_bedroom = "卧室";
}

class goodfriend{//好朋友类
public:
    goodfriend();
    void visit();//在类外创建函数,则要在类内进行声明
    building* build;
};

goodfriend::goodfriend() {//创建建筑物对象
    build = new building;//在堆区创建
}

void goodfriend::visit()//参观函数,访问另一个类的属性
{
    cout << "好朋友类访问公共属性" << build->m_sittingroom << endl;
    cout << "好朋友类访问私有属性" << build->m_bedroom << endl;
}

 void test1() {//测试案例代码
     goodfriend f;//创建一个类对象后会先调用构造函数good friend(),这个函数里面有building另外一个类的对象创建,则调用building这个类的构造函数
     f.visit();//使用类函数则要先创建类对象,然后调用类里的函数声明。
 }
 //类外写成员函数

int main()
{
    test1();
    system("pause");
    return 0;
}

成员函数做友元

注意先声明building然后再定义朋友类,再定义建筑物类,再利用构造函数初始化朋友类,创建类对象,然后构造函数赋初值给类属性,重要的是,要先定义朋友类,再定义建筑类,不然程序会出错的。

#include<iostream>
#include<string>
using namespace std; 
//友元,有些私有的属性想要类外的某些函数或者是类来访问,就需要友元
//friend为关键字
//实现:成员函数做友元
class building;

class goodfriend{//好朋友类
public:
    goodfriend();
    void visit1();//可以访问私有内容
    void visit2();//只能访问公共内容
    building* build;
};


class building {//建筑物类
    //告诉编译器这个类下面的visit1函数作为本类的好朋友,可以访问私有内容
    friend void goodfriend::visit1();
public:
    building();
    string m_sittingroom;
private:
    string m_bedroom;
};
goodfriend::goodfriend() {//创建建筑物对象
    build = new building;//在堆区创建
}
building::building() {//构造函数赋初值
    m_sittingroom = "客厅";
    m_bedroom = "卧室";
}

void goodfriend::visit1() {
    cout << "访问类的公共属性:" << build->m_sittingroom << endl;
    cout << "访问私有属性:" <<build->m_bedroom<< endl;
}
void goodfriend::visit2() {
    cout << "访问类的公共属性:" << build->m_sittingroom << endl;
}
 void test1() {//测试案例代码
     goodfriend f;//创建一个类对象后会先调用构造函数good friend(),这个函数里面有building另外一个类的对象创建,则调用building这个类的构造函数
     f.visit1();
     f.visit2();
 }
 //类外写成员函数

int main()
{
    test1();
    system("pause");
    return 0;
}

运算符重载

对于内置的数据类型,编译器知道如何运算。

而c++中有自定义数据类型,程序往往不知道如何去计算自定义数据类型

因此需要自己进行运算符重载,使用关键字operate

加号运算符重载

先新建一个自定义数据类型——类,然后对于类对象的直接相加计算机不知道如何计算——》需要进行加号运算符重载

代码示例:

这个是使用成员函数重载的+号运算符

由于是两个类对象直接相加,所以这里新建一个类对象让成员分别相加,最后返回person类型,这里的this指针是指向调用这个函数的类对象例如式子为p1+p2,则p1调用这个函数,并传入p2。

    //成员函数重载+运算符
person operator+(person &p)
{
   person t;
   t.m_age = this->m_age + p.m_age;
   t.m_high = this->m_high + p.m_high;
   return t;
}

 全局函数重载+运算符,这里是把两个类对象直接传入,不用this指针了。

//全局函数重载+运算符
person operator+(person p1, person p2)
{
    person t;
    t.m_age = p1.m_age + p2.m_age;
    t.m_high = p1.m_high + p2.m_high;
    return t;
}

输入输出运算符重载

这里需要知道两个流,在c++中cin和cout是输入输出最基本的符号

⭐cin

cin的类型是istream也就是说cin是一个istream类型的对象

⭐cout

cout类型为ostream,不是函数

istreamostreamiostream库中最常用的两个基础类型,本别为输入流和输出流(流为字符序列,主要操作对象为IO

🆗基本知识了解后我们就可以写运算符重载函数了

代码示例:

分析:

首先对于<<运算符重载,第一先判定需要完成的功能——输出类对象的所有成员

由上图可知,参数1为cout,参数2为输出对象——类对象p

而返回值是怎么定的呢?由于会存在链式输出,当一个<<完成后返回值如果是类则无法输出如下图:

则>>运算符重载同理,也是先判断要完成的功能和参数,然后根据实际案例,确定返回值,即可完成运算符重载。

//重载<<运算符
ostream& operator<<(ostream&cout,const person& p)
{
    cout << p.m_age<<" ";
    cout << p.m_high <<endl ;
    return cout;
}

//重载>>运算符
istream& operator>>(istream& cin, person& p)//这里不和重载<<运算符一样,不要加const
{
    cin >> p.m_age;
    cin >> p.m_high;
    return cin;
}

自增运算符重载

自增运算符分为两种——++a,a++

代码示例(成员函数实现):

分析:

首先我们要完成的是前缀的自增运算符,完成功能是要先把所有类对象的成员+1然后返回所有成员加一后的类对象

而后缀是需要先返回值再加值,而这一个不能先写return再加一,无法操作,那么这里可以借助新建一个类对象来对过去的数据进行存储,返回这个旧数据,而把调用这个函数的类对象的成员值增加1

为了区分两个自增运算符重载,对于后缀的参数里加(int),前缀的无参数

//重载后缀的自增运算符
person operator++(int)
{
    person t;
    t.m_age = this->m_age++;
    t.m_high = this->m_high++;
    return t;
}
//重载前缀的自增运算符
person operator++()
{
    ++this->m_age;
    ++this->m_high;
    return *this;
}

==运算符重载

代码示例:

分析:

这里要实现的功能是判断两个类对象是否相等,参数是判断两个关系的类对象,返回值为布尔类型,在运算符重载函数中需要写if语句,通过判断两个的成员是否相等来判断两个类对象是否相等

//重载==关系运算符
bool operator==(person p1,person p2)
{
    if (p1.m_age == p2.m_age&& p1.m_high == p2.m_high)
    {
        return 1;
    }else
    {
        return 0;
    }
}

函数调用运算符()重载

代码示例:

这里示例是要实现调用的类对象加上传进去的两个整型数据,然后返回。

//函数调用重载
person operator()(int a,int b)
{
    this->m_age  = this->m_age +a;
    this->m_high  = this->m_high +b;
    return *this;
}

以上的运算符完整重载代码:

#define  _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<fstream>
using namespace std; 
class person
{
public:
    int m_age;
    int m_high;
    //成员函数重载+运算符
//person operator+(person &p)
//{
 //   person t;
 //   t.m_age = this->m_age + p.m_age;
 //   t.m_high = this->m_high + p.m_high;
 //   return t;
//}
    //重载后缀的自增运算符
    person operator++(int)
    {
        person t;
        t.m_age = this->m_age++;
        t.m_high = this->m_high++;
        return t;
    }
    //重载前缀的自增运算符
    person operator++()
    {
        ++this->m_age;
        ++this->m_high;
        return *this;
    }
    //函数调用重载
    person operator()(int a,int b)
    {
        this->m_age  = this->m_age +a;
        this->m_high  = this->m_high +b;
        return *this;
    }
};
//全局函数重载+运算符
person operator+(person p1, person p2)
{
    person t;
    t.m_age = p1.m_age + p2.m_age;
    t.m_high = p1.m_high + p2.m_high;
    return t;
}
//重载关系运算符
bool operator==(person p1,person p2)
{
    if (p1.m_age == p2.m_age&& p1.m_high == p2.m_high)
    {
        return 1;
    }
}
//重载<<运算符
ostream& operator<<(ostream&cout,const person& p)
{
    cout << p.m_age<<" ";
    cout << p.m_high <<endl ;
    return cout;
}
//重载>>运算符
istream& operator>>(istream& cin, person& p)//这里不和重载<<运算符一样,不要加const
{
    cin >> p.m_age;
    cin >> p.m_high;
    return cin;
}

void test1() {
    person p1;
    person p2;
    person p3;
    p1.m_age = 12;
    p1.m_high = 153;
    p2.m_age = 18;
    p2.m_high = 192;
    cout<<p1 + p2;
    cout << p1++;//12 153
    cout << p1;//13 154
    cout << ++p2;//19 193
    cin >> p3;//19 193
    if (p2 == p3) {
        cout << "你们身高和年龄一样啊" << endl;
    }
    person p4 = p3(10, 20);//29 213
    cout << p4;//29 213
}
int main()
{
    test1();
    system("pause");
    return 0;
}

总结:

对于c++的友元以及运算符重载就介绍到这里,欢迎点赞收藏文章和专栏(会分享更多代码知识),文章如有错误,请大佬指出,谢谢(●'◡'●)

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

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

相关文章

Paper - CombFold: Predicting structures of large protein assemblies 推理流程

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/136165853 CombFold 是一种新的组装技术&#xff0c;可以利用 AlphaFold-Multimer 预测的可能的亚复合物的结构&#xff0c;来构建大型蛋白质复合…

【Oracle】玩转Oracle数据库(二):体系结构、存储结构与各类参数

前言 嘿伙计们&#xff01;准备好了吗&#xff1f;今天我要和你们探讨一个酷炫的话题——Oracle数据库&#xff01;&#x1f389; 在这篇博文【Oracle】玩转Oracle数据库&#xff08;二&#xff09;&#xff1a;体系结构、存储结构与各类参数&#xff0c;我们要揭开Oracle数据库…

甲方紧急需求带来封闭式开发,项目负责人如何做好团队共识?

在职场上总会遇到各种类型的甲方金主&#xff0c;项目开展过程中也难免出现多种变更要求。本期小编就结合一位希赛学员的工作经验分享&#xff0c;一起来大家探讨下&#xff1a;面对甲方的紧急需求&#xff0c;项目经理该如何做才能带领团队克服困难&#xff0c;最终促成项目收…

【Prometheus】node-exporter、server、Grafana安装与配置

基于Prometheus和K8S构建智能化告警系统 一、Prometheus对kubernetes的监控二、node-exporter组件安装和配置2.1、node-exporter介绍2.2、安装node-exporter【1】拉取镜像【2】编写yaml文件【3】运行pod【4】获取数据 三、Prometheus server安装和配置3.1、创建sa账号&#xff…

Mysql 权限与安全管理

0 引言 MySQL是一个多用户数据库&#xff0c;具有功能强大的访问控制系统&#xff0c;可以为不同用户指定允许的权限。MySQL用户可以分为普通用户和root用户。root用户是超级管理员&#xff0c;拥有所有权限&#xff0c;包括创建用户、删除用户和修改用户的密码等管理权限&…

单机环境搭建Redis伪集群

1、Redis版本 [rootwsdhla ~]# redis-server -v Redis server v6.2.6 sha00000000:0 mallocjemalloc-5.1.0 bits64 buildbf23dac15dfc00fa[rootwsdhla ~]# redis-cli -v redis-cli 6.2.62、创建节点目录 创建6个节点目录&#xff0c;分别复制一份redis.conf并编辑&#xff1a…

电路设计(20)——数字电子钟的multism仿真

1.设计要求 使用数字芯片&#xff0c;设计一个电子钟&#xff0c;用数码管显示&#xff0c;可以显示星期&#xff0c;时、分、秒&#xff0c;可以有按键校准时间。有整点报警功能。 2.设计电路 设计好的multism电路图如下所示 3.芯片介绍 时基脉冲使用555芯片产生。在仿真里面…

hal/SurfaceFlinger/perfetto实战需求问题探讨作业-千里马framework开发

背景 hi&#xff0c;粉丝朋友们&#xff1a; 在新课halperfettosurfaceflinger https://mp.weixin.qq.com/s/LbVLnu1udqExHVKxd74ILg 推出后&#xff0c;各位学员朋友们都积极响应&#xff0c;开始马不停蹄的学习&#xff0c;学员学习后希望有更多的实战案例或者项目拿来练手&…

自动化上位机开发C#100例:雷赛运动控制卡EtherCAT总线卡C#封装类

自动化上位机开发C#100例:雷赛运动控制卡EtherCAT总线卡C#封装类 文章目录 LTDMC.dll下载LTDMC.cs LTDMC.dll C#调用封装下载ICard.cs 运动控制卡接口Card.cs 运动控制卡抽象类CardLTDMC.cs 雷赛运动控制卡EtherCAT总线卡实现类CardList.cs 总线卡列表封装 LTDMC.dll下载 最新…

OpenAI公布阻止国家相关威胁行为者对人工智能的恶意使用(包括中国、朝鲜、伊朗、俄罗斯)

曾梦想执剑走天涯&#xff0c;我是程序猿【AK】 目录 简述总结 简述 本篇幅公布OpenAI于2月14日公布的”阻止国家相关威胁行为者对人工智能的恶意使用“一文&#xff0c;其中提及到阻止并限制了来自&#xff08;包括中国、朝鲜、伊朗、俄罗斯&#xff09;的一些用户的使用&…

实习日志15

1.大改了一下界面 1.1.识别与验真 1.2.历史记录 2.改了几个bug 2.1.改json格式用JSON.stringify(value,null,2); 2.2.内嵌页面值与原页面值重复 2.3.验真条件判断 if (isVerifyCell.getValue() "不需要") {if (verifyResultCell.getValue() ! "未查验")…

IDEA实现序列化时如何自动生成serialVersionUID

实现步骤&#xff1a;1.安装GenerateSerialVersionUID插件 2.点击idea左上角File -> Settings -> Editor -> Inspections -> 搜索 Serialization issues &#xff0c;找到 Serializable class without ‘serialVersionUID’ ->打上勾&#xff0c;再点击Apply-&…

计算机功能简介:EC, NVMe

一 EC是指Embedded Controller 主要应用于移动计算机系统和嵌入式计算机系统中&#xff0c;为此类计算机提供系统管理功能。EC的主要功能是控制计算机主板上电时序、管理电池充电和放电&#xff0c;提供键盘矩阵接口、智能风扇接口、串口、GPIO、PS/2等常规IO功能&#xff0c;…

MySQL-锁(LOCK)

文章目录 1. 锁是什么&#xff1f;2. 全局锁2.1 相关语法2.2 特点 3. 表级锁3.1 表锁3.1.1 共享读锁&#xff08;S&#xff09;3.1.2 排它写锁&#xff08;X&#xff09; 3.2 元数据锁&#xff08;MDL&#xff09;3.2 意向锁&#xff08;IS、IX&#xff09; 4. 行级锁4.1 行锁 …

【力扣 - 二叉树的中序遍历】

题目描述 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 提示&#xff1a; 树中节点数目在范围 [0, 100] 内 -100 < Node.val < 100方法一&#xff1a;递归 思路与算法 首先我们需要了解什么是二叉树的中序遍历&#xff1a;按照访问左子树——…

【Linux系统化学习】深入理解文件系统(Ext2文件系统)

目录 前言 磁盘的物理结构 物理结构 磁头和盘片工作解析图 盘面区域划分图&#xff08;俯视盘面图&#xff09; 扇区的寻址、定位&#xff08;CHS定位&#xff09; 磁盘存储的逻辑抽象结构 LBA定址 文件系统 磁盘分区 EXT2文件系统 组块中的信息介绍 查看inode编号…

代码随想录算法训练营|二叉树总结

二叉树的定义&#xff1a; struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode():val(0),left(nullptr),right(nullptr){}TreeNode(int val):val(val),left(nullptr),right(nullptr){}TreeNode(int val,TreeNode* left,TreeNode* right):val(val),left(left),…

【Linux】软件包管理器 yum | vim编辑器

前言: 软件包管理器 yum和vim编辑器讲解 文章目录 软件包管理器 yum编辑器-vim四种模式普通模式批量化注释和批量化去注释末行模式临时文件 软件包管理器 yum yum&#xff08;Yellowdog Updater, Modified&#xff09;是一个在基于 RPM&#xff08;管理软件包的格式和工具集合&…

Smart Link和Monitor Link简介

定义 Smart Link&#xff0c;又叫做备份链路。一个Smart Link由两个接口组成&#xff0c;其中一个接口作为另一个的备份。Smart Link常用于双上行组网&#xff0c;提供可靠高效的备份和快速的切换机制。 Monitor Link是一种接口联动方案&#xff0c;它通过监控设备的上行接口…

Facebook Horizon:探索虚拟现实中的社交空间

随着科技的不断进步&#xff0c;虚拟现实&#xff08;VR&#xff09;技术正成为社交互动和娱乐体验的新前沿。在这个数字时代&#xff0c;Facebook作为全球最大的社交媒体平台之一&#xff0c;正在引领虚拟社交的新时代&#xff0c;其推出的虚拟社交平台Facebook Horizon成为了…