C++ day04(友元 friend、运算符重载、String字符串)

目录

【1】友元 friend

1》概念

2》友元函数 

3》友元类

 4》友元成员函数

 【2】运算符重载

1》概念

2》友元函数运算符重载

 ​编辑

 3》成员函数运算符重载

4》赋值运算符与类型转换运算符重载

 5》注意事项

【3】String 字符串类


【1】友元 friend

1》概念

定义:

类实现了数据的隐藏和封装,类的数据成员一般定义为私有成员,仅能通过类的成员函数才能访问到。如果数据成员定义为公共的,则又破坏了封装性。但是某些情况下,需要频繁访问类的成员,特别是在对某些成员函数多次调用时,由于参数传递、类型检查和安全性检查等都需要时间开销,会影响到程序的运行效率。


友元是一种定义在类外部的普通函数,蛋挞需要在类内进行声明,为了和该类的成员函数加以区别,要在声明前加关键字friend。友元不是成员函数,但是它能够访问类内的所有成员。


作用:

 提高程序的运行效率,但是破坏了类的封装性和隐藏性,使得非成员函数能够访问类的私有成员。导致程序维护性变差,所以使用友元要慎重。

友元更为常用的应用是运算符重载,这种应用可以提高软件系统的灵活性。


分类:

1.友元函数

2.友元类

3.友元成员函数

2》友元函数 

友元函数是一种“声明”在类内,实际在类外的普通函数。

#include <iostream>using namespace std;class Girl
{
private:int age;public:Girl(int age):age(age){}int get_age() const{cout << &age << endl;return 18;}// 1. "声明"友元函数friend void access_true_age(Girl&);
};// 2. 定义友元函数
void access_true_age(Girl& g)
{// 突破权限,直接操作Girl类的私有成员;cout << &g.age << endl;cout << "真实年龄:" << g.age << endl;// 修改g.age = 18;cout << "修改后年龄:" << g.age << endl;
}int main()
{Girl g(45);cout << g.get_age() << endl;// 通过友元函数访问Girl的年龄access_true_age(g);return 0;
}

 需要注意的是:

1.由于友元函数不属于成员函数,因此友元函数没有this 指针,访问类的成员的时候只能通过对象

2.友元函数在类中的“声明”可以写在类的任何部分,不受权限修饰符的影响。

3.理论上,一个友元函数可以是多个类的友元函数,只需要在各个类中分别“声明”。

3》友元类

当一个类B成为了另一个类A的友元类的时候,类B可以访问类A的所有成员。

需要注意的是:

1.友元关系是单向的,不具有交换性。

    如果类B是类A的友元类,类A不一定是类B的友元类

2.友元关系不具有传递性

    如果类C是类B的友元类,类B是类A的友元类,类C不一定是类A 的友元类。

3.友元关系不能被继承

#include <iostream>using namespace std;class A
{
private:string str = "A私有";// “声明”友元类friend class B;
};class B
{
public:void func(A& a){
//        cout << this->str << endl; 错误:this是B对象不是A对象cout << a.str << endl;//可以直接操作类A的私有成员a.str =  "我改了";cout << a.str << endl;}
};int main()
{A a;
//    cout << a.str << endl; 错误,全局不能调用类A的私有成员B b;b.func(a);return 0;
}

 4》友元成员函数

在友元类的任何成员函数中都可以访问其他类的成员,但是友元成员函数把友元范围限制在一个成员函数中。

例如,类B的某个成员函数称为了类A 的友元成员函数,这样类B的该成员函数就可以访问两类A的所有成员了。

#include <iostream>using namespace std;// 3. 因为第二步中用到了类A,提前声明类A
class A;// 2. 编写类B,并真正声明友元成员函数
class B
{
public:void func(A&);
};class A
{
private:string str = "A私有";// 1. 确定友元的函数格式并“声明”friend void B::func(A&);
};// 4. 类外定义友元成员函数
void B::func(A & a)
{//  cout << this->str << endl; 错误:this是B对象不是A对象cout << a.str << endl;a.str =  "我改了";cout << a.str << endl;
}int main()
{A a;//    cout << a.str << endl; 错误B b;b.func(a);return 0;
}

 【2】运算符重载

1》概念

如果把运算符看做是一个函数,则运算符也可以想函数一样重载。

C++中预定义的运算符的操作对象只能是基本数据类型。但实际上对于很多用户的自定义类型,也是需要类似的运算操作,这时可以在C++中重新定义这些运算符,赋予已有运算符新的功能,使它能够用于特定类型,执行特定的操作。


可以被重载的运算符:

算术运算符:+、-、*、/、%、++、--

位操作运算符:&、|、~、^(位异或)、<<(左移)、>>(右移)

逻辑运算符:!、&&、||

比较运算符:<、>、>=、<=、==、!=

赋值运算符:=、+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=

其他运算符:[]、()、->、,、new、delete、new[]、delete[]

不被重载的运算符:

成员运算符“.”、指针运算符“*”、三目运算符“? :”、sizeof、作用域“::”

2》友元函数运算符重载

 

#include <iostream>using namespace std;/*** @brief The Integer class 整数类*/
class Integer
{
private:int value;public:Integer(int value):value(value){}int get_value() const{return value;}// 友元函数“声明”friend Integer operator +(const Integer&,const Integer&);friend Integer operator ++(Integer&); // 前置friend Integer operator ++(Integer&,int); // 后置
};//友元函数定义
Integer operator +(const Integer& i1,const Integer& i2)
{return i1.value + i2.value; // 隐式调用构造函数
}Integer operator ++(Integer& i)
{return ++i.value; // 隐式调用构造函数
}Integer operator ++(Integer& i,int)
{return i.value++; // 隐式调用构造函数
}int main()
{Integer i1(1);Integer i2(2);Integer i3 = i1 + i2;cout << i3.get_value() << endl; // 3cout << (i1++).get_value() << endl; // 1cout << (++i1).get_value() << endl; // 3return 0;
}

 3》成员函数运算符重载

成员函数运算符重载与友元函数运算符重载的最大区别:友元函数运算符重载的第一个参数,在成员函数中使用this 指针代替,即使用成员函数重载的运算符重载相比友元函数的参数少一个。

 

#include <iostream>using namespace std;/*** @brief The Integer class 整数类*/
class Integer
{
private:int value;public:Integer(int value):value(value){}int get_value() const{return value;}// 声明成员函数Integer operator +(const Integer&); // 双目Integer operator ++(); // 前置Integer operator ++(int) // 后置{return this->value++;}
};Integer Integer::operator +(const Integer& i)
{return this->value + i.value;
}Integer Integer::operator ++()
{return ++this->value;
}int main()
{Integer i1(1);Integer i2(2);Integer i3 = i1 + i2;cout << i3.get_value() << endl; // 3cout << (i1++).get_value() << endl; // 1cout << (++i1).get_value() << endl; // 3return 0;
}

4》赋值运算符与类型转换运算符重载

如果程序员不写赋值运算符重载函数,编译器会为类自动添加一个赋值运算符重载函数,且此函数支持链式调用,因此只能使用成员函数运算符重载。

#include <iostream>using namespace std;class Value
{
public:int value = 0;// 1. 构造函数// 2. 拷贝构造// 3. 析构函数// 4. 赋值运算符重载// 编译器自动添加:Value& operator =(const Value& v){value = v.value;return *this;}
};int main()
{Value v; // 构造函数Value v2(v); // 拷贝构造Value v3 = v2; // 拷贝构造v.value = 1;v3 = v; // 赋值运算符cout << v3.value << endl; // 1return 0;
}

 类型转换运算符与赋值运算符的符号都是 = ,因此类型转换运算符重载函数比较特殊,以便于与赋值运算符重载进行区分,同样类型转换运算符重载函数也只支持成员函数运算符重载。

#include <iostream>using namespace std;class Value
{
private:int value;public:Value(int value):value(value){}int get_value() const{return value;}// 类型转换运算符重载函数operator int()//value转换为int类型{return value;}
};int main()
{// int → ValueValue v = 1; // 隐式构造// Value → intint i = v; // 类型转换运算符重载函数cout << i << endl; // 1return 0;
}

 5》注意事项

1.运算符重载限制在C++已有的运算符范围内,不能创建新的运算符。

2.运算符重载不能改变运算符的优先级、结合性、操作数和语法结构。

3.运算符重载不能改变基本类型的计算规则,只能更改包含自定义类型的计算规则。

4.运算符重载实现的功能应该与元运算符相近。

5.运算符重载函数不支持参数默认值。

6.通常单目运算符使用成员函数重载,双目运算符使用友元函数重载。

【3】String 字符串类

#include <iostream>
#include <string.h>using namespace std;int main()
{string s; // 生成一个空字符串cout << "判断字符串是否为空:" <<  s.empty() << endl; // 1string s1 = "Thursday"; // 隐式调用构造函数,参数const char*string s2("Thursday"); // 显式调用上面的构造函数cout << "判断是s1是否等于s2:" << (s1 == s2) << endl; // 1string s3 = s1; // 隐式调用拷贝构造string s4(s2); // 显式调用拷贝构造cout << "判断是s1是否等于s2:" << (s3 == s4) << endl; // 1s = s4; // 赋值运算符cout << s << endl; // "Thursday"// 参数1:const char* 原字符串// 参数2:保留几个字符string s5("ABCDEFG",2);//保留前两个字符cout << s5 << endl; // ABs = "ABCDEFG";// 参数1:string 原字符串// 参数2:不保留前几个字符string s6(s,2);cout << s6 << endl; // CDEFG// 参数1:字符串长度// 参数2:字符内容string s7(6,'A');cout << s7 << endl; // AAAAAA// 交换swap(s6,s7);cout << s6 << " " << s7 << endl; // AAAAAA CDEFGs = s6+s7; // 拼接cout << s << endl; // AAAAAACDEFG// 向后追加s.append("123");cout << s << endl; // AAAAAACDEFG123// 向后追加单字符s.push_back('%'); // AAAAAACDEFG123%// 插入// 参数1:插入的位置// 参数2:插入的内容s.insert(1,"222"); // A222AAAAACDEFG123%// 参数1:删除的起始位置// 参数2:删除的字符数s.erase(4,10);cout << s << endl; // A222123%// 参数1:替换的起始位置// 参数2:替换的字符数// 参数3:替换的内容s.replace(0,3,"******");cout << s << endl; // ******2123%s.clear(); // 清空cout << s.length() << endl; // 0char c[20];s = "1234567890";// 参数1:拷贝的目标// 参数2:拷贝的字符数// 参数3:拷贝的起始位置s.copy(c,3,1);cout << c << endl; // 234// C → C++ 直接赋值即可// char* → stringchar* c1 = "Tom";char c2[] = "Jerry";string sc1 = c1;string sc2 = c2;cout << sc1 << "&" << sc2 << endl; // Tom&Jerry// C++ → C// string → char[]s = "abcd";char ch[10];strcpy(ch,s.c_str()); // c_str()返回值的const char*不稳定cout << ch << endl;return 0;
}

今天的分享就到这里结束啦,如果有哪里写的不好的地方,请指正。
如果觉得不错并且对你有帮助的话点个关注支持一下吧! 

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

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

相关文章

YOLOv5改进——添加SimAM注意力机制

目录 一、SimAM注意力机制核心代码 二、修改common.py 三、修改yolo.py ​三、建立yaml文件 四、验证 一、SimAM注意力机制核心代码 在models文件夹下新建modules文件夹&#xff0c;在modules文件夹下新建一个py文件。这里为simam.py。复制以下代码到文件里面。 import…

吴恩达深度学习笔记:卷积神经网络(Foundations of Convolutional Neural Networks)2.7-2.8

目录 第四门课 卷积神经网络&#xff08;Convolutional Neural Networks&#xff09;第二周 深度卷积网络&#xff1a;实例探究&#xff08;Deep convolutional models: case studies&#xff09;2.7 Inception 网络&#xff08;Inception network&#xff09;2.8 使 用 开 源 …

75. 颜色分类

思路 先排最小的数&#xff0c;将最小的数都放至列表前面 则0~r-1都是最小值 从r到len(nums)-1继续进行排序&#xff0c;从尾部开始&#xff0c;将最大值放置尾部 class Solution(object):def sortColors(self, nums):""":type nums: List[int]:rtype: None …

Python | Leetcode Python题解之第468题验证IP地址

题目&#xff1a; 题解&#xff1a; class Solution:def validIPAddress(self, queryIP: str) -> str:if queryIP.find(".") ! -1:# IPv4last -1for i in range(4):cur (len(queryIP) if i 3 else queryIP.find(".", last 1))if cur -1:return &q…

Window系统编程 - 文件操作

前言 各位师傅大家好&#xff0c;我是qmx_07&#xff0c;今天主要介绍使用windows系统编程操作读写文件 文件 CreateFile()函数讲解 介绍:该函数用于打开文件或者I/O流设备&#xff0c;文件、文件流、目录、物理磁盘、卷、控制台缓冲区、磁带驱动器、通信资源、mailslot 和…

Jenkins Pipline流水线

提到 CI 工具&#xff0c;首先想到的就是“CI 界”的大佬--]enkjns,虽然在云原生爆发的年代,蹦出来了很多云原生的 CI 工具,但是都不足以撼动 Jenkins 的地位。在企业中对于持续集成、持续部署的需求非常多,并且也会经常有-些比较复杂的需求,此时新生的 CI 工具不足以支撑这些很…

看门狗电路设计

看门狗电路设计 看门狗是什么应用架构图TPV6823芯片功能硬件时序图为什么要一般是要保持200个毫秒左右的这种低电平的时间看门狗电路实际应用与条件 看门狗是什么 硬件看门狗芯片&#xff0c;Watch DogTimer&#xff0c;可用于受到电气噪音、电源故障、静电放电等影响(造成软件…

LSTM(长短时记忆网络)

一、引言 在处理序列数据时&#xff0c;循环神经网络&#xff08;RNN&#xff09;虽然能够处理序列数据并保留历史信息&#xff0c;但在实践中发现它对于捕捉长时间依赖关系的能力有限&#xff0c;尤其是在训练过程中容易遇到梯度消失或梯度爆炸的问题。为了解决这些问题&…

Nginx基础详解5(nginx集群、四七层的负载均衡、Jmeter工具的使用、实验验证集群的性能与单节点的性能)

续Nginx基础详解4&#xff08;location模块、nginx跨域问题的解决、nginx防盗链的设计原理及应用、nginx模块化解剖&#xff09;-CSDN博客 目录 14.nginx集群&#xff08;前传&#xff09; 14.1如何理解单节点和集群的概念 14.2单节点和集群的比较 14.3Nginx中的负载均衡…

QT入门教程攻略 QT入门游戏设计:贪吃蛇实现 QT全攻略心得总结

Qt游戏设计&#xff1a;贪吃蛇 游戏简介 贪吃蛇是一款经典的休闲益智类游戏&#xff0c;玩家通过控制蛇的移动来吃掉地图上的食物&#xff0c;使蛇的身体变长。随着游戏的进行&#xff0c;蛇的移动速度会逐渐加快&#xff0c;难度也随之增加。当蛇撞到墙壁或自己的身体时&…

Laravel Filament 如何配置多语言支持

演示 一、安装拓展包outerweb/filament-translatable-fields composer require outerweb/filament-translatable-fields配置模型 该套件包含一个名为 HasTranslations 的特性&#xff0c;用于使 Eloquent 模型具备多语言功能。翻译值以 JSON 格式存储&#xff0c;并不需要额外…

Run the FPGA VI 选项的作用

Run the FPGA VI 选项的作用是决定当主机 VI 运行时&#xff0c;FPGA VI 是否会自动运行。 具体作用&#xff1a; 勾选 “Run the FPGA VI”&#xff1a; 当主机 VI 执行时&#xff0c;如果 FPGA VI 没有正在运行&#xff0c;系统将自动启动并运行该 FPGA VI。 这可以确保 FPG…

夜间数据库IO负载飙升?MySQL批量删除操作引发的问题排查

目录 问题现象 问题分析 修改建议 总结 问题现象 近日&#xff0c;某用户反馈他们的MySQL数据库实例在凌晨时段会频繁出现IO负载急剧上升的情况&#xff0c;这种状态会持续一段时间&#xff0c;随后自行恢复正常。为了查明原因&#xff0c;该用户通过DBdoctor工具收集了相…

第十三章 Redis短信登录实战(基于Redis)

目录 一、概述 1.1. Session复制 1.2. 使用Redis 二、基于Redis实现共享Session登录 2.1. 实现思路 2.2. 功能实现的主要代码 2.2.1. 用户业务接口 2.2.2. 用户业务接口实现类 2.2.3. 用户控制层 2.2.4. 登录拦截器 2.2.5. 拦截器配置类 2.3. 优化登录拦截器 完…

电池大师 2.3.9 | 专业电池管理,延长寿命优化性能

Battery Guru 显示电池使用情况信息&#xff0c;测量电池容量&#xff08;mAh&#xff09;&#xff0c;并通过有用技巧帮助用户改变充电习惯&#xff0c;延长电池寿命。支持显示电池健康状况&#xff0c;优化电池性能。 大小&#xff1a;9.6M 百度网盘&#xff1a;https://pan…

26.删除有序数组中的重复项

题目::26. 删除有序数组中的重复项 - 力扣&#xff08;LeetCode&#xff09; 思路:只要不和前面的数一样就可以移动指针&#xff0c;进行赋值 代码: class Solution { public:int removeDuplicates(vector<int>& nums) {int slow 0 ;for(int fast 1; fast < …

髓质脊髓三叉神经核文献阅读笔记

文献阅读 1.RNA-seq 对于大量RNA测序&#xff0c;收集第30天的类器官。使用FastPure细胞/组织总RNA分离试剂盒根据制造商的方案提取总RNA。采用Nanodrop 2000分光光度计测定RNA浓度和纯度。使用Agilent 2100生物分析仪和2100 RNA纳米6000检测试剂盒评估RNA样品的完整性。简单…

选型工单管理系统,从原理到应用全面解读

工单管理系统提升客户支持效率&#xff0c;优化内部协作&#xff0c;强化数据分析。选型需明确需求&#xff0c;比较系统功能和特性&#xff0c;评估试用后选择最适合的系统。ZohoDesk凭其多渠道支持、智能分配、自动化工具、协作工具和数据分析能力&#xff0c;成为企业优选。…

Redis篇(缓存机制 - 基本介绍)(持续更新迭代)

目录 一、缓存介绍 二、经典三缓存问题 1. 缓存穿透 1.1. 简介 1.2. 解决方案 1.3. 总结 2. 缓存雪崩 2.1. 简介 2.2. 解决方案 2.3. 总结 3. 缓存击穿 3.1. 简介 3.2. 解决方案 3.3. 总结 4. 经典三缓存问题出现的根本原因 三、常见双缓存方案 1. 缓存预热 1…

MySQL进阶 - 索引

01 索引概述 【1】概念&#xff1a;索引就是一种有序的数据结构&#xff0c;可用于高效查询数据。在数据库表中除了要保存原始数据外&#xff0c;数据库还需要去维护索引这种数据结构&#xff0c;通过这种数据结构来指向原始数据&#xff0c;这样就可以根据这些数据结构实现高…