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.rhkb.cn/news/446268.html

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

相关文章

BUUCTF-greatescape1

发现有ftp包和tcp包居多 下载解压是个流量包&#xff0c;使用wiresharh打开&#xff0c;CTRLF&#xff0c;按下图搜索ftp tcp18流发现ssc.key 传送&#xff0c;在19流发现key内容 复制保存为ssc.key, 加载key解密tls&#xff0c;再追踪tls流可得flag INS{OkThatWasWay2Easy} …

多元线性回归:机器学习中的经典模型探讨

引言 多元线性回归是统计学和机器学习中广泛应用的一种回归分析方法。它通过分析多个自变量与因变量之间的关系&#xff0c;帮助我们理解和预测数据的行为。本文将深入探讨多元线性回归的理论背景、数学原理、模型构建、技术细节及其实际应用。 一、多元线性回归的背景与发展…

基于Java的旅游网站管理系统—计算机毕业设计源码39235

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对旅游网站等问题&#xff0c;对旅游网站进行…

一区大黄蜂!人工蜂群算法优化!ABC-CNN-LSTM-MATT多特征分类预测

一区大黄蜂&#xff01;人工蜂群算法优化&#xff01;ABC-CNN-LSTM-MATT多特征分类预测 目录 一区大黄蜂&#xff01;人工蜂群算法优化&#xff01;ABC-CNN-LSTM-MATT多特征分类预测分类效果基本介绍程序设计参考资料 分类效果 基本介绍 1.Matlab实现ABC-CNN-LSTM-MATT人工蜂群…

PDF转JPG神器!一键转换,轻松搞定文档分享

各位亲爱的小伙伴们&#xff0c;有没有遇到过需要把PDF文件转换成JPG图片的情况呢&#xff1f;今天我就来给大家推荐几款好用的PDF转JPG工具&#xff0c;让我们一起来看看这些工具的详细介绍和使用感受吧&#xff01; 一、福昕转换器 直通车&#xff08;粘贴到浏览器打开&…

获取时隔半个钟的三天与el-time-select

摘要&#xff1a; 今天遇到需求是配送时间&#xff0c;时隔半个钟的排线&#xff01;所以需要拼接时间&#xff01;例如2024-10-08 14&#xff1a;30&#xff0c;2024-10-08 15&#xff1a;00&#xff0c;2024-10-08 15&#xff1a;30 <el-form-item label"配送时间&a…

优先算法1--双指针

“一念既出&#xff0c;万山无阻。”加油陌生人&#xff01; 目录 1.双指针--移动零 2.双指针-复写零 ok&#xff0c;首先在学习之前&#xff0c;为了方便大家后面的学习&#xff0c;我们这里需要补充一个知识点&#xff0c;我这里所谓的指针&#xff0c;不是之前学习的带有…

如何构建高效的公路工程资料管理系统?

本文介绍了构建高效的公路工程资料管理系统的方法&#xff0c;涵盖了系统需求分析、功能设计、开发平台选择、开发过程、系统上线与培训、持续改进与维护等关键环节。通过合理规划和科学管理&#xff0c;可以确保系统满足用户需求&#xff0c;提高工作效率&#xff0c;保障公路…

react18+react-transition-group实现路由切换过度

效果如下 官网安装对应的插件 创建对应的样式 .fade-enter {opacity: 0; } .fade-exit {opacity: 1; } .fade-enter-active {opacity: 1; } .fade-exit-active {opacity: 0; } .fade-enter-active, .fade-exit-active {transition: opacity 500ms; }const location useLoca…

STM32 | STM32F4OTA_ESP8266_Bootloader为引导程序远程更新的代码(APP)

更新。点击上方"蓝字"关注我们 01、思路 >>> STM32F4OTA_ESP8266_Bootloader为引导程序 远程更新的代码&#xff08;APP&#xff09;:远程更新的APP Ymoden_server&#xff1a;为运行在Linux的TCP服务器 备注&#xff1a;STM32 OTA远程更新需要连接热点 电…

【实战项目】——Boost搜索引擎(五万字)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、项目的相关背景 1.1、什么是Boost库&#xff1f; 1.2、什么是搜索引擎&#xff1f; 1.3、为什么要做Boost库搜索引擎&#xff1f; 二、搜索引擎的宏观原…

【优选算法篇】双指针的优雅舞步:C++ 算法世界的浪漫探索

文章目录 C 双指针详解&#xff1a;基础题解与思维分析前言第一章&#xff1a;对撞指针1.1 移动零解题思路图解分析C代码实现易错点提示代码解读 1.2 复写零解题思路算法步骤C代码实现易错点提示代码复杂度 1.3 盛最多水的容器1. 题目链接2. 题目描述解法一&#xff08;暴力求解…

MySQL SELECT 查询(三):查询常用函数大全

MySQL SELECT 查询&#xff08;三&#xff09;&#xff1a;查询常用函数大全 1. 单行函数 单行函数是 SQL 中一类重要的函数&#xff0c;它们可以对单行数据进行处理&#xff0c;并返回单个结果。单行函数可以嵌套使用&#xff0c;并提供灵活的数据处理能力。 1.1 定义 只对单…

H7-TOOL的LUA小程序教程第14期:任意波形信号发生器,0-20mA输出和微型数控电源(2024-10-11,已更新)

LUA脚本的好处是用户可以根据自己注册的一批API&#xff08;当前TOOL已经提供了几百个函数供大家使用&#xff09;&#xff0c;实现各种小程序&#xff0c;不再限制Flash里面已经下载的程序&#xff0c;就跟手机安装APP差不多&#xff0c;所以在H7-TOOL里面被广泛使用&#xff…

矩阵系统源码搭建,oem贴牌,技术指导

一、技术选型与整合 多种技术的融合 矩阵系统通常需要整合多种技术&#xff0c;包括前端技术、后端技术、数据库技术、服务器技术等。选择合适的技术栈并确保它们能够良好地协同工作是一个挑战。例如&#xff0c;前端可能使用 React 或 Vue.js&#xff0c;后端可能使用 Java Sp…

解决新版Android studio不能连接手机的问题

我要说的是一个特例&#xff0c;装了22年的版本AS可以正常连接手机&#xff0c;装了23年以后新版本&#xff0c;AS不能正常连接手机了&#xff0c;但是在CMD控制台可以正常的执行adb命令&#xff0c;并且CMD和AS都是指向D:\android_sdk\platform-tools\adb.exe 一、 为什么会出…

消息队列面试题——第二篇

1. rocketmq、rabbitmq、kafka的区别 架构设计和消息模型 特性rocketmqrabbitmqkafka消息模型基于主题和消费组&#xff0c;支持发布/订阅和点对点两种模型基于队列模型&#xff0c;支持发布/订阅和点对点两种模型基于分区的主题模型&#xff0c;主要用于日志流式处理和高吞吐…

完成Sentinel-Dashboard控制台数据的持久化-同步到Nacos

本次案例采用的是Sentinel1.8.8版本 一、Sentinel源码环境搭建 1、下载Sentinel源码工程 git clone https://github.com/alibaba/Sentinel.git 2、导入到idea 这里可以先运行DashboardApplication.java试一下是否运行成功&#xff0c;若成功&#xff0c;源码环境搭建完毕&a…

IDEA Sping Boot 多配置文件application Maven动态切换

新建application-dev.yml与application-prod.yml pom.xml文件下添加profiles等 让idea识别出配置文件 <profiles><profile><id>dev</id><properties><!-- 环境标识&#xff0c;需要与配置文件的名称相对应 --><profiles.active>dev&…

基于京东:HotKey实现自动缓存热点Key!!!

一.引言 某些热点数据&#xff0c;我们提前如果能够预判到的话&#xff0c;可以提前人工给数据加缓存&#xff0c;也就是缓存预热&#xff0c;将其缓存在本地或者Redis中&#xff0c;提高访问性能同时&#xff0c;减低数据库压力&#xff0c;也减轻后端服务的压力。但是&#…