C++的类和对象(七):友元、内部类

目录

友元

友元函数

友元类

内部类

匿名对象

拷贝对象时的一些编译器优化

再次理解类和对象


友元

基本概念:友元提供了一种突破封装的方式,有时提供了便利,但是友元会增加耦合度,破坏了封装,所以友元不宜多用(开后门)

格式:friend 函数声明

分类:友元函数和友元类

友元函数

解决问题:类外无法访问成员函数

注意事项:

1、友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字

class Date
{friend ostream& operator<<(ostream& _cout, const Date& d);friend istream& operator>>(istream& _cin, Date& d);
public:Date(int year = 1900, int month = 1, int day = 1): _year(year), _month(month), _day(day){}
private:int _year;int _month;int _day;
};ostream& operator<<(ostream& _cout, const Date& d)
{_cout << d._year << "-" << d._month << "-" << d._day;return _cout; 
}istream& operator>>(istream& _cin, Date& d)
{_cin >> d._year;_cin >> d._month;_cin >> d._day;return _cin;
}int main()
{Date d;cin >> d;cout << d << endl;return 0;
}

2、友元函数可以访问类的私有和保护成员,但不是类的成员函数

3、友元函数不能用const修饰(没必要)

4、友元函数可以在类定义的任何地方声明,不受类的访问限定符限制

5、一个函数可以是多个类的友元函数

6、友元函数的调用与普通函数的调用原理相同

7、不想用友元就用get和set

友元类

注意事项:

1、友元的关系是单向的,不具有交换性(你是我的朋友我允许你看我,但不知道你让不我看你)

Time类中声明Date类是其友元类,则可以在Date类中访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行:

class Time
{friend class Date;//声明日期类为时间类的友元类,则在日期类中就直接访问Time类中的私有成员变量public:Time(int hour = 0, int minute = 0, int second = 0): _hour(hour), _minute(minute), _second(second){}private:int _hour;int _minute;int _second;
};class Date
{
public:Date(int year = 1900, int month = 1, int day = 1): _year(year), _month(month), _day(day){}void SetTimeOfDate(int hour, int minute, int second){// 直接访问时间类私有的成员变量_t._hour = hour;_t._minute = minute;_t._second = second;}private:int _year;int _month;int _day;Time _t;
};

2、友元关系不能传递(C是B的友元,B是A的友元,在未声明的情况下C不是A的友元)

3、友元关系不能继承

4、友元关系是双向时,两个类都可以访问对方的成员变量和成员函数

内部类

基本概念:一个类定义在另一个类的内部,这个内部类就叫内部类

注意事项:

1、类不占用空间(编译后不占用空间)

#include <iostream>
using namespace std;class A
{
public:class B{private:int _b1;};
private:int _a1;int _a2;
};int main()
{cout << sizeof(A)<<endl;return  0;
}

想象中在A类中嵌套一个B类应该是下的代码是这样的,但实际上不是:

2、内部类受外部类的类域的限制

3、内部类是外部类的友元(内部类可以访问外部类的成员,但是外部类不能访问内部类的成员)

4、内部类可以定义在外部类的任意位置

5、内部类可以直接访问外部类中的static成员,不需要外部类的对象或类名

#include <iostream>
using namespace std;class A
{
private:static int k;int h;
public:class B // B天生就是A的友元{public:void foo(const A& a){cout << k << endl;//OK,this->kcout << a.h << endl;//OK,this->h}};
};int A::k = 1;int main()
{A::B b;b.foo(A());return 0;
}
  • A() :匿名的临时对象
  • b.foo(A()): 将匿名对象作为参数传递给了类 A 中嵌套类 B 的成员函数 foo()

6、sizeof(外部类) = 外部类的大小,和内部类没有任何关系

匿名对象

格式:类名()

注意事项:

1、匿名对象的括号内可以有参数

2、匿名对象的声明周期只在当前一行(第1行定义匿名对象,第2行时该匿名对象销毁)

#include <iostream>
using namespace std;
class A
{
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}~A(){cout << "~A()" << endl;}private:int _a;
};class Solution
{
public:int Sum_Solution(int n){//...return n;}
};int main()
{A aa1;//有名对象A();//匿名对象A(10);//匿名对象A aa2(2);//有名对象Solution().Sum_Solution(10);return 0;
}

3、匿名对象可以提供一些便利(当我们只是向调用对象的内容时有名写两行,匿名写一行)

//形式一
Solution s1;
s1.func(10);//形式二
Solution().Sum_Solution(10);

拷贝对象时的一些编译器优化

基本概念:在传参和传返回值时,一般编译器会做一些优化,减少对象的拷贝

连续构造 + 拷贝构造 = 优化为直接构造

连续构造 + 拷贝构造 = 优化为一个构造

连续拷贝构造 + 拷贝构造 = 优化为一个拷贝构造

连续拷贝构造 + 赋值重载 = 无法优化

再次理解类和对象

        计算机不认识现实生活中的实体,只认识二进制格式的数据,如果想要计算机认识现实中的实体,用户必须通过某种面向对象的语言,对实体进行描述,然后通过编写程序,创建对象后计算机才可以认识,比如像要让计算机认识洗衣机就需要:

  1. 用户先对现实中的洗衣机实体进行抽象认知,即在思想层面对洗衣机进行认识,洗衣机有什么属性(成员变量)和功能(成员函数)
  2. 此时,人脑中已经对洗衣机有了一个较为清醒的认识,通过某种面相对象的语言将洗衣机用类来进行描述,就可以让计算机知道人脑中对洗衣机的认识
  3. 然后,在计算机中就有了一个洗衣机类,但它只是站在计算机的角度对洗衣机进行描述的,只有利用洗衣机类实例化出具体的洗衣机对象,用户才可以模拟现实中洗衣机实体的功能
#include <iostream>
#include <string>class WashingMachine {
private:int capacity; // 洗衣容量bool isOn; // 洗衣机是否开启std::string brand; // 品牌public:WashingMachine(int cap, const std::string& b) : capacity(cap), isOn(false), brand(b) {}void turnOn() {isOn = true;std::cout << "Washing machine turned on." << std::endl;}void turnOff() {isOn = false;std::cout << "Washing machine turned off." << std::endl;}void washClothes() {if(isOn) {std::cout << "Washing clothes..." << std::endl;} else {std::cout << "Please turn on the washing machine first."<<std:endl;;}}
};int main() {WashingMachine myWasher(5, "ABC");myWasher.turnOn();myWasher.washClothes();return 0;}

~over~

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

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

相关文章

记录工作中莫名其妙的bug

1、问题&#xff1a;办公室的电脑突然除了我之外&#xff0c;都不能访问我们的线上系统了 原因&#xff1a;因为是内网&#xff0c;同事有刚刚升级了Windows11&#xff0c;配置的DNS被清了&#xff0c;还有同事换了公司的新电脑&#xff0c;还没有配DNS 位于&#xff1a;C /Win…

C#,入门教程(27)——应用程序(Application)的基础知识

上一篇: C#,入门教程(26)——数据的基本概念与使用方法https://blog.csdn.net/beijinghorn/article/details/124952589 一、什么是应用程序 Application? 应用程序是编程的结果。一般把代码经过编译(等)过程,最终形成的可执行 或 可再用 的文件称为应用程序。可执行文…

vue3项目随笔1

1,Eslint Prettier 报错情况&#xff1a; 解决办法&#xff1a; &#xff08;1&#xff09;下载Prettier - code formatter &#xff08;2&#xff09;配置setting.json文件 文件 -> 首选项 -> 设置 -> 用户 -> Eslint "editor.defaultFormatter":…

北斗卫星在桥隧坡安全监测领域的应用及前景展望

北斗卫星在桥隧坡安全监测领域的应用及前景展望 北斗卫星系统是中国独立研发的卫星导航定位系统&#xff0c;具有全球覆盖、高精度定位和海量数据传输等优势。随着卫星导航技术的快速发展&#xff0c;北斗卫星在桥隧坡安全监测领域正发挥着重要的作用&#xff0c;并为相关领域…

c语言的字符串函数详解

文章目录 前言一、strlen求字符串长度的函数二、字符串拷贝函数strcpy三、链接或追加字符串函数strcat四、字符串比较函数strcmp五、长度受限制字符函数六、找字符串2在字符串1中第一次出现的位置函数strstr七、字符串切割函数strtok&#xff08;可以切割分隔符&#xff09;八、…

【python】爬取杭州市二手房销售数据做数据分析【附源码】

一、背景 在数据分析和市场调研中&#xff0c;获取房地产数据是至关重要的一环。本文介绍了如何利用 Python 中的 requests、lxml 库以及 pandas 库&#xff0c;结合 XPath 解析网页信息&#xff0c;实现对链家网二手房销售数据的爬取&#xff0c;并将数据导出为 Excel 文件的过…

day-21 前 K 个高频元素

思路&#xff1a;用ans[]存储频次最高的k个元素&#xff0c;用anslen[]存储对应的索引&#xff0c;将nums进行排序依次统计每个元素出现次数&#xff0c;再判断是否需要对ans[]和anslen[]进行替换&#xff0c;最后ans即为答案 注意点&#xff1a;遍历结束后&#xff0c;还需要…

linux 使用docker安装 postgres 教程,踩坑实践

linux 使用docker安装 postgres 教程 踩坑实践,安装好了不能远程访问。 防火墙已关闭、postgres 配置了允许所有ip 访问、网络是通的。端口也是开放的&#xff0c;就是不能用数据库链接工具访问。 最后发现是云服务器端口没开 ,将其打开 到这一步完全正确了&#xff0c;但是…

Java项目:56 ssm681基于Java的超市管理系统+jsp

作者主页&#xff1a;源码空间codegym 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 功能包括:商品分类&#xff0c;供货商管理&#xff0c;库存管理&#xff0c;销售统计&#xff0c;用户及角色管理&#xff0c;等等功能。项目采…

SpringBoot(异常处理)

SpringBoot&#xff08;异常处理&#xff09; 1.基本介绍 2.debug异常处理机制 1.找到 DefaultErrorViewResolver 2.下断点 3.debug启动&#xff0c;浏览器输出一个不存在的页面 4.第一次查找 error/404 1.查看目前要找的视图名 2.准备去查找资源 3.准备从四个默认存放静态资…

【Linux进程信号】信号的发送与保存

【Linux进程信号】信号的发送与保存 目录 【Linux进程信号】信号的发送与保存阻塞信号1. 信号其他相关常见概念2. 在内核中的表示3. sigset_t4. 信号集操作函数sigprocmasksigpendingsignal测试这几个系统调用接口 进程地址空间第三讲捕捉信号1. 内核如何实现信号的捕捉2. siga…

Java八股文(Git)

Java八股文のGit Git Git Git 是什么&#xff1f;它有什么作用&#xff1f; Git 是一种分布式版本控制系统&#xff0c;用于管理源代码的变更和追踪。 它可以记录文件更改的历史&#xff0c;帮助多人协同开发&#xff0c;并提供了回滚、分支管理等功能。 Git 和 SVN&#xff0…