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

【C -> Cpp】由C迈向Cpp (6):静态、友元和内部类

标题:【C -> Cpp】由C迈向Cpp (6):静态、友元和内部类

@水墨不写bug


(图片来源于网络)


目录

(一)静态成员

(二)友元

 (三)内部类

(四)深入理解类和对象、总结


正文开始: 

(一)静态成员

        C语言中有静态的概念,比如静态函数和静态变量。

静态变量:存储在静态区,随着主函数的开始而创建并初始化,随着程序结束而销毁。选择创建静态变量,会使变量的生命周期延长到程序结束。

静态函数则是不同的概念:静态函数只能在当前源文件中访问,不能被其他源文件访问调用。选择定义静态函数的作用是将函数的作用域限制在当前源文件内,并且可以避免与其他源文件中定义的同名函数发生冲突。

        Cpp中,由于新增了类和对象的特性,对静态变量的处理就有所不同了。

         类中是可以创建静态变量的,由于静态变量存储在静态区,只初始化一次,所以一个类(Class)内部(定义)包含有的静态变量是可以通过任意一个这个Class创建的对象来访问的,这也就表明了这个静态变量是属于这个类的,而不是单独属于某个实例化的对象。

        如果我们执行下面这一段代码:

#include<cstdlib>
#include<iostream>
using namespace std;
class A
{public:private:static int _a;int _b;int _c;
};
int main()
{A aa;cout << sizeof(aa) << endl;return 0;
}

 结果可能会让你惊讶:静态对象_a不是存储在对象aa中的!

        1.静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区。

(类的成员函数指针也不存放在类内,而是存放在公共的代码段)

 其次,类静态对象的定义是在类外部的。

class A
{
public:private:static int _a;int _b;int _c;
};int A::_a = 5;

         2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明

         访问方式:

        类静态成员对象有两种访问方式:

        1)通过实例化的对象访问;

    A aa;//实例化一个对象aa._a++;//通过对象访问

        2)通过类名访问;

    A::_a++;//直接通过类名访问

        3. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员

>同时就是说:静态成员函数只可以访问静态变量

 4. 静态成员也是类的成员,受public、protected、private 访问限定符的限制


(二)友元

        友元是通过一个关键字(friend)来实现的;我们在实现一个类的时候,通常把成员函数定义为共有(public),而把成员变量定义为私有(private)。

        如果我们在项目中想要通过重载cout来输出自己的自定义类型对象时,一定会遇到这样的问题:


ostream& operator<<(const Date d) 
{out << this->_year << " " << this->_month << " " << this->_day;out << endl;return out;
}

        由于用类对象调用重载后的函数时,参数的顺序首先是this,其次是其他的对象。所以调用重载后的cout会十分的别扭,而与常规的逻辑不同:

    cout<<d1;

         解决方法就是第一个参数必须是cout,其次是其他参数。由于类内部定义的函数的第一个参数必是this指针,所以这个逻辑正确的函数必须在类外定义。

        但是由于类外的函数不能访问类的private的成员函数,所以为了解决这一问题,Cpp就引入“友元”的概念:

        成为友元的函数可以突破private的限制,直接访问类的私有成员变量。

        友元分为:#友元函数和友元类#

 注意:

        1)友元提供了一种突破封装的方式,有时提供了便利;

        2)但是友元会增加耦合度,破坏了封装,所以友元不宜多用。

        通过定义友元函数,我们可以写出逻辑正确的cout重载函数:

ostream& operator<<(ostream& out, const Date d) 
{out << d._year << " " << d._month << " " << d._day;out << endl;return out;
}

 函数的效果:


 (三)内部类

        什么是内部类?如果一个类,它定义在另一个类的内部,那么这个定义在内部的类就称为“内部类”。

示例:

class A
{class B{int _c;    };
};

此时,B就是A的内部类。 

内部类也是一个类,只不过他被A的作用域又封装了一层,想要找到B,则要:

//创建一个类B,需要在A的作用域中去寻找A::B aa;

 内部类是一个独立的类,它是外部类A的友元类:        

        内部类B可以访问A的私有成员,而A不能访问B的私有成员。

        (内部可以访问外部,而不能反着来)

 其他特性:
        1. 内部类可以定义在外部类的public、protected、private都是可以的。
        2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。
        3. sizeof(外部类)=外部类,和内部类没有任何关系。

(四)深入理解类和对象、总结

        假如将来你要开一家外卖公司,需要打造你的项目,这时你该如何保存信息?

        创建多个类:外卖骑手,商家,顾客类;

每个类包含的信息(包含的成员变量),拥有的功能(实现的函数)都是最必要的:

骑手:姓名,电话,实时位置信息等;

商家:店名,位置,菜品,价格信息等;

顾客:姓名,电话,住址信息等;

        这些成员变量就是根据实际需求来定义的。对于这些类,他们之间也会有交互,需要实现交互函数,这就是后话了。


        类和对象是一种能够将现实生活中的关系相对较好的表现出来,这也是面向对象编程的实际需求。

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

考虑显示需求:

        对于商家,他们都有一个特征:他们是卖东西的,需要客户。

        对于骑手,他们的特征是:他们是接单送单的,需要商家的订单。

        对于顾客,他们的特征是:他们是需要产品的,要在商家那里消费的,需要商家。

        据此,我们可以把所有的商家抽象为一类,创建一个商家类;把所有的骑手抽象为一个类,创建一个骑手类;把所有的顾客抽象为一个类,创建一个顾客类。

        类是对象的抽象,对象是类的实际体现。

        类的属性和功能来源于生活中的实际需要。


 

用一张图总结:

 


完~

未经作者同意禁止转载 

相关文章:

【C -> Cpp】由C迈向Cpp (6):静态、友元和内部类

标题&#xff1a;【C -&#xff1e; Cpp】由C迈向Cpp &#xff08;6&#xff09;&#xff1a;静态、友元和内部类 水墨不写bug &#xff08;图片来源于网络&#xff09; 目录 &#xff08;一&#xff09;静态成员 &#xff08;二&#xff09;友元 &#xff08;三&#xff09…...

探索Playwright:Python下的Web自动化测试革命

在如今这个互联网技术迅速发展的时代&#xff0c;web应用的质量直接关系着企业的声誉和用户的体验。因此&#xff0c;自动化测试成为了保障软件质量的重要手段之一。今天&#xff0c;我将带大家详细了解一款在测试领域大放异彩的神器——Playwright&#xff0c;并通过Python语言…...

先有JVM还是先有垃圾回收器?很多人弄混淆了

是先有垃圾回收器再有JVM呢&#xff0c;还是先有JVM再有垃圾回收器呢&#xff1f;或者是先有垃圾回收再有JVM呢&#xff1f;历史上还真是垃圾回收更早面世&#xff0c;垃圾回收最早起源于1960年诞生的LISP语言&#xff0c;Java只是支持垃圾回收的其中一种。下面我们就来刨析刨析…...

关于 vs2019 c++20 规范里的一个全局函数 _Test_callable

&#xff08;1&#xff09;看名思议&#xff0c;觉得这个函数可以测试其形参是否是可以被调用的函数&#xff0c;或可调用对象&#xff1f; 不&#xff0c;这个名字不科学。有误导&#xff0c;故特别列出。看下其源码&#xff08;该函数位于 头文件&#xff09;&#xff1a; 辅…...

07-Fortran基础--Fortran指针(Pointer)的使用

07-Fortran基础--Fortran指针Pointer的使用 0 引言1 指针&#xff08;Poionter&#xff09;的有关内容1.1 一般类型指针1.2 数组指针1.3 派生类(type)指针1.4 函数指针 2 可运行code 0 引言 Fortran是一种广泛使用的编程语言&#xff0c;特别适合科学计算和数值分析。Fortran 9…...

日期差值,

日期差值 ac代码 #include<iostream> using namespace std; int ans0; int get(int n){int mon[14]{0,31,28,31,30,31,30,31,31,30,31,30,31};ans0;int m_dayn%100;int m_month(n/100)%100;int m_year(n/10000);ansm_day;while(m_month--){//加上月数if((m_year%40&…...

GMV ES6直流变频多联空调机组室外机工作原理

GMV ES6直流变频多联空调机组室外机工作原理如下&#xff1a; 内机为制冷模式运行时&#xff0c;室外机根据室内机的运行负荷需求启动运行&#xff0c;室外换热器作为系统的冷凝器&#xff0c;各制冷室内机的换热器并联作为系统的蒸发器&#xff0c;通过室内机的送回风循环实现…...

中国开源 AI 大模型之光-InternLM2

今天给大家带来 AI 大模型领域的国产之光 - InternLM2&#xff0c;在10B量级开源大模型领域取得了全球 Top 3 的成绩&#xff0c;仅次于 Meta 发布的 Llama-3&#xff0c;在国内则是第一名的存在&#xff01; 简介 InternLM2是由上海人工智能实验室和商汤科技联合研发的一款大型…...

【嵌入式开发】Arduino人机界面及接口技术:独立按键接口,矩阵按键接口,模拟量按键接口(基础知识介绍)

“生活总是让我们遍体鳞伤,但到后来,那些受伤的地方一定会变成我们最强壮的地方。” 🎯作者主页: 追光者♂🔥 🌸个人简介: 📝[1] CSDN 博客专家📝 🏆[2] 人工智能领域优质创作者🏆 🌟[3] 2022年度博客之星人工智能领域TOP4🌟 🌿[4] …...

element ui Tree树形控件

lazy 是否懒加载子节点&#xff0c;需与 load 方法结合使用 boolean 默认为falseload 加载子树数据的方法&#xff0c;仅当 lazy 属性为true 时生效 function(node, resolve)使用懒加载load不需要再使用data&#xff0c;利用resolve返回值即可注意&#xff1a;第一层的数据要写…...

AI 绘画神器 Fooocus 图生图:图像放大或变化、图像提示、图像重绘或扩充、反推提示词、生成参数提取、所需模型下载

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里&#xff0c;订阅后可阅读专栏内所有文章。 大家好&#xff0c;我是水滴~~ 本文讲述 Fooocus 的图生图功能&#xff0c;主要内容包括&#xff1a;图像放大或变化、图像提示、图像重绘或扩充、反推…...

yolov8 模型架构轻量化 | 极致降参数量

模型轻量化加速是深度学习领域的重要研究方向&#xff0c;旨在减小模型的体积和计算复杂度&#xff0c;从而提高在资源受限设备上的运行效率&#xff0c;模型参数量在轻量化加速中扮演着至关重要的角色。 首先&#xff0c;模型参数量直接决定了模型的复杂度和存储空间需求。随…...

uniapp 小程序低功耗蓝牙配网 ble配网 物联网

1.获取蓝牙列表 bleList.vue <template><view><button touchstart"startSearch">获取蓝牙列表</button><scroll-view :scroll-top"scrollTop" scroll-y class"content-pop"><viewclass"bluetoothItem&q…...

服务器防火墙有什么用防护策略

随着互联网的飞速发展&#xff0c;服务器的安全问题日益凸显。为了保护服务器免受网络攻击和恶意入侵的威胁&#xff0c;人们引入了防火墙的概念。服务器防火墙作为保护服务器的第一道防线&#xff0c;具有重要的作用。那么服务器防火墙有什么用&#xff1f; 首先&#xff0c;服…...

27.哀家要长脑子了!

目录 1.316. 去除重复字母 - 力扣&#xff08;LeetCode&#xff09; 2. 1209. 删除字符串中的所有相邻重复项 II - 力扣&#xff08;LeetCode 哎哟 烦死了 刚刚不小心退出又没保存 又要写一遍 烦死了 最近刷题不得劲啊 感觉这脑子没长一点 1.316. 去除重复字母 - 力扣&am…...

Redis实战—验证码登录注册

目录 基于Session Controller层 Service层 ServiceImpl层 ​编辑校验登录状态 ThreadLocal 登录拦截器 添加拦截器到Config Controller层实现 基于Redis ServiceImpl 新增刷新拦截器 添加拦截器到Config 基于Session Controller层 /*** 发送手机验证码*/PostMappi…...

对话机器人技术解说

一、RAG介绍 如何不通过微调模型来提高LLM性能&#xff0c;检索增强生成&#xff08;RAG&#xff09;是未来的发展方向。 Embedding&#xff1a;将文档的句子或单词块转换为数字向量。就向量之间的距离而言&#xff0c;彼此相似的句子应该很近&#xff0c;而不同的句子应该离…...

红黑树底层封装map、set C++

目录 一、框架思考 三个问题 问题1的解决 问题2的解决&#xff1a; 问题3的解决&#xff1a; 二、泛型编程 1、仿函数的泛型编程 2、迭代器的泛型编程 3、typename&#xff1a; 4、/--重载 三、原码 红黑树 map set 一、框架思考 map和set都是使用红黑树底层&…...

压力给到 Google,OpenAI 发布 GPT-4o 来了

北京时间5月14日凌晨1点&#xff0c;OpenAI 开启了今年的第一次直播&#xff0c;根据官方消息&#xff0c;这次旨在演示 ChatGPT 和 GPT-4 的升级内容。在早些时候 Sam Altman 在 X 上已经明确&#xff0c;「我们一直在努力开发一些我们认为人们会喜欢的新东西&#xff0c;对我…...

【SpringSecurity源码】过滤器链加载流程

theme: smartblue highlight: a11y-dark 一、前言及准备 1.1 SpringSecurity过滤器链简单介绍 在Spring Security中&#xff0c;过滤器链&#xff08;Filter Chain&#xff09;是由多个过滤器&#xff08;Filter&#xff09;组成的&#xff0c;这些过滤器按照一定的顺序对进…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架&#xff0c;用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录&#xff0c;以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度

文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...

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

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

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值&#xff0c;最大值左侧的数值严格单调递增&#xff0c;最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值&#xff0c;最小值左侧的数值严格单调递减&#xff0c;最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...