C++ | 类和对象(下)(static成员、友元、内部类、匿名对象)

目录

​编辑

static成员

static性质简介

static属于整个类,属于所有对象

static成员的声明与定义

static函数

友元friend

友元特性简介

友元关系讲解

内部类

特性一

特性二

匿名对象

结语


static成员

static性质简介

static成员在类里面是非常独特的,因为这个成员并不存在于类里面,就像是函数一样

我们先来看这么一段程序:

class A
{
public:int _a;static int _b;
};int main()
{A aa1;cout << sizeof(aa1) << endl;return 0;
}

我们能看到,这段程序的目的就是看这个类的大小,我们的类里面有一个普通的int成员和一个static成员,但是结果为 4,这说明static成员是不存在于类中的

static属于整个类,属于所有对象

这句话的意思就是,我们无论创建了多少个对象,所有的对象想要用这个static成员,那么使用的就都是同一个static成员,因为这个static成员属于所有对象

我们可以验证一下这个特性,来看这么一段代码:

ps:该段代码中有关于static成员声明与定义的问题和static成员函数的问题,稍后会讲到

class A
{
public:A(){_b++;}~A(){_b--;}//静态成员函数static int get_b(){return _b;}private:int _a;static int _b;//声明
};int A::_b = 0;//定义int main()
{A aa1;A aa2;A aa3;A aa4;cout << A::get_b() << endl;return 0;
}

我们能看到,每个对象创建出来时,都会调用对应的构造函数,而我们在构造函数里面就干一件事:将静态成员++

又因为所有对象共用同一个static成员,所以我们每创建一个对象,我们的_b就会++一下

最后,我们再通过静态成员函数将静态成员变量取出,就能看到具体此时有几个对象还存在了

static成员的声明与定义

因为是static成员,所以是不能在构造函数中进行初始化的

那我们可以按如下方式赋值吗?

private:int _a = 0;static int _b = 0;

答案是否定的,因为这里的值是给初始化列表看的,但是我们的static成员都不在类里面,所以这种方法是行不通的

而静态成员的其中一个特性就是——静态成员变量必须在类外面初始化

而类中的只是声明,而类外面的是定义,定义时不加关键字static,但是需要指定类域,如下:

class A
{
private:int _a;static int _b;
};int A::_b = 0;

static函数

如果我们将static成员定义为私有,那我们就无法在类外面使用该成员

由此,C++里就搞出了一个static函数,如下:

class A
{
public:static int get_b(){return _b;}private:int _a;static int _b;
};int A::_b = 0;

如上,我们写了一个函数get_b,通过将这个函数设为公有我们就能取到_b

并且由于这个函数是static函数,所以没有this指针,也就无法访问到除了静态成员以外的其他成员

友元friend

友元特性简介

当一个类A有特殊情况,必须要访问类B中的私有成员时,我们就可以使用友元

如下:

class A
{friend class B;int _a = 1;
};class B
{
public:int getnum(){return _t._a;}
private:A _t;
};int main()
{B b1;cout << b1.getnum() << endl;return 0;
}

我们能看到,类A中的_a是私有的,这就意味着其他类是无法使用的,但是我们可以将类B设置为类A的友元,这样子我们的类B就能访问到类A的私有成员了

添加友元的方式就是在类的声明前面加一个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;
}

如上是我们在上文中讲到的Date类(日期类),如若有不了解的,可以点下面链接复习一下:

Date 日期类的实现

和友元类差不多,都是声明前面加一个friend

友元关系讲解

这里关系到一个问题,我们可以联系现实:

我喜欢你,你就一定得喜欢我吗?

我把你当朋友,你就一定得把我当朋友吗?

我是你爸的朋友,我就一定得是你的朋友吗?

这几句话就讲解了:友元关系不是相互的,我把你当朋友,你可以用我的东西,但是我不一定能用你的东西,除非你把我当成朋友

同时,友元关系是不能继承的,这个知识点了解就好,这关系到以后会讲的继承章节的相关内容

内部类

内部类相对来说比较简单

我们在一个类里面,能定义一个int变量,能定义一个static变量,同样的,我们也可以定义一个类类型的变量,也就是在类里面定义一个类

特性一

class A
{int _a = 0;static int _s;class B // 内部类{int _k;void getAnum(const A& a){cout << _s << endl;cout << a._a << endl;}};};
int A::_s = 0;

如上,我们可以总结出内部类的其中一个特性:

内部类天生就是外部类的友元,即内部是外部的朋友,所以内部类可以使用外部类的私有

但是外部类不是内部类的友元,所以外部类不能使用内部类的私有

也就是:不是我把你当朋友,你就一定得把我当朋友

特性二

我们再来看这么一段代码:

class A
{int _a = 0;static int _s;class B // 内部类{int _k;void getAnum(const A& a){cout << _s << endl;cout << a._a << endl;}};};
int A::_s = 0;int main()
{A a1;cout << sizeof(a1) << endl;return 0;
}

我们可以看到,对类A的大小进行统计以后发现,类B是不计在类A里面的

由此我们可以得出第二个特性:

内部类和外部类是两个平行的类,内部类唯一的特殊点就是受到类域的限制和天生友元关系

也就是说,这两个类之间并没有说谁大谁小,都是两个一样的类,只不过需要访问内部类的话就需要对类域进行限制,如下:

A a1;
A::B _b;

匿名对象

我们来看这么一个例子(假设有一个类A已存在):

A a1; //有名对象
A(); //匿名对象

匿名对象和有名对象的区别在于:有名对象的生命周期是当前域结束时才到

但是匿名对象的生命周期是他所在的那一行,也就是即用即销毁

我们来看下面这一段代码:

class A
{
public:A(){cout << "A()" << endl;}~A(){cout << "~A()" << endl;}
};int main()
{A a1;A();A a2;return 0;
}

我们可以明显看到,匿名对象那里是刚声明完就销毁了,而有名对象是直到程序结束了才销毁

至于匿名对象的好处,就是调用起来会更省事

现在看起来可能会觉得没什么用,但是当我们在学习STL相关知识的时候就能体会到真香定律(bushi

举个栗子:

#include<map>int main()
{map<int, int> m1;//使用有名对象的插入方式pair< int, int> s1(1, 2);m1.insert(s1);//使用匿名对象的插入方式m1.insert(pair<int, int>(1, 2));//使用隐式类型转换为匿名对象的插入方式m1.insert({ 1,2 });return 0;
}

map是stl中的一个数据结构,而我们每次插入数据都需要插入一个pair类型的数据进去

如果是有名对象的话,我们就需要将pair类型的变量定义出来再插入进去(s1)

但如果是匿名对象的话,我们直接在插入里面定义一个匿名对象,即用即销毁也无所谓,反正数据插入进去了

当然还有更好的方法,就是走隐式类型转换,当然这些显然有点超纲,我们只需要知道匿名在未来的学习中非常常见即可

结语

距离上一篇更新已经过去了三个月整了,这三个月一直忙于C++和算法,现在也算是抽出时间来补一补博客了,突然有种高中知识学完了但发现初中的作业还没写完的感觉(苦笑)

如果感觉这篇博客对各位有帮助的话,希望可以多多支持喔!!!

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

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

相关文章

Golang之OpenGL(一)

使用OpenGL实现窗口中绘制三角形&#xff08;纯色|彩色&#xff09;、正方形&#xff08;变色&#xff09; 一、简单实现窗口绘制三角形二、绘制的多颜色三角形&#xff08;基于 ‘ 简单实现窗口绘制三角形 ’ &#xff09;1、在顶点着色器和片段着色器中添加了颜色的输入和输出…

反制攻击者-蚁剑低版本

目录 安装 攻击者获取防守方的权限 防守方反制攻击者 防守方获取攻击者的shell权限 安装 安装蚁剑2.0.7版本 链接&#xff1a;https://pan.baidu.com/s/1t40UxkZ2XuSWG6VCdGzvDw?pwd8888 提取码&#xff1a;8888 下载好后先打开Loader文件夹下的.exe文件&#xff0c;打…

赛蓝企业管理系统 AuthToken/Index 身份认证绕过漏洞复现

0x01 产品简介 赛蓝企业管理系统是一款为企业提供全面管理解决方案的软件系统&#xff0c;它能够帮助企业实现精细化管理&#xff0c;提高效率&#xff0c;降低成本。系统集成了多种管理功能&#xff0c;包括但不限于项目管理、财务管理、采购管理、销售管理以及报表分析等&am…

【iOS】——GCD总结

同步和异步的区别 同步执行等待操作完成&#xff0c;而异步执行允许程序在操作完成前继续运行&#xff0c;提高了效率和响应性。这里的关键就是上一个操作需不需要等待当前操作的执行&#xff0c;如果需要就是同步&#xff0c;如果不需要就是异步。 异步有开启新线程的能力但…

合作伙伴中心Partner Center中添加了Copilot预览版

目录 一、引言 二、Copilot 功能概述 2.1 Copilot 简介 2.2 Copilot 的核心功能 2.3 Copilot 的访问和使用 三、Copilot 的使用方法 3.1 Copilot 功能区域 3.2 Copilot 使用示例 3.2.1 编写有效提示 3.2.2 使用反馈循环 四、负责任的人工智能 4.1 Copilot 结果的可…

Golang处理Word文档模板实现标签填充|表格插入|图标绘制和插入|删除段落|删除标签

本教程主要实现【Golang处理Word文档模板实现标签填充|表格插入|图标绘制和插入|删除段落|删除标签】。 本文源码&#xff1a;https://gitee.com/songfayuan/go-zero-demo 教程源码分支&#xff1a;master 分支&#xff08;_examples/word-template/fill-word-template.go&…

win 10 局域网共享

1&#xff0c;打开共享 控制面板\网络和 Internet\网络和共享中心\高级共享设置 &#xff08;在控制面板界面建议使用大图片或小图标容易找到目标&#xff09; 或者直接复制红色部分&#xff0c;然后打开此电脑&#xff0c;粘贴到地址栏直接回车即可直接到达几面 打开如下2个…

达梦数据库一体机在宜昌市财政局上线了!

财政作为国家治理的基础和重要支柱&#xff0c;其数字化转型已成为构建现代财政制度的必由之路&#xff0c;引领着财政管理体系向更高效、更智能的方向迈进。 达梦数据全面助力财政信息化转型与智能化发展&#xff0c;采用 DAMEGN PAI I 系列数据库一体机&#xff0c;为宜昌市财…

Unity Camera

课程目标 1. 了解摄像机&#xff08;camera&#xff09;不同视角的设计与实现&#xff1b;2. 感受在不同摄像机视角下观察虚拟场景。 喜欢玩游戏或者看3D动漫的朋友可以回忆在虚拟场景中摄像头的运动变化带来的视觉感受&#xff0c;例如&#xff1a;摄像头给场景中的主角来个…

马来西亚原生静态IP注册的账号稳定吗?

马来西亚作为东南亚重要的经济体之一&#xff0c;其网络基础设施和互联网服务水平在近年来有了显著提升。静态IP作为一种固定的互联网协议地址&#xff0c;对于某些特定的网络应用和需求非常重要。本文将围绕马来西亚原生静态IP注册的账号稳定性进行探讨&#xff0c;分析其在不…

【Python系列】Python 字典合并

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

pytorch基础模块:Tensorboard、Dataset、Transforms、Dataloader

Tensorboard、Dataset、Transforms、Dataloader 该文档主要参考【土堆】的视频教程&#xff1a;pytorch入门教程–土堆 一、Tensorboard 安装tensorboard&#xff1a;pip install tensorboard 使用步骤&#xff1a; 引入相关库&#xff1a;from torch.utils.tensorboard i…

LinkedList接口源码解读

LinkedList 接口源码解读&#xff08;一&#xff09; 前言 因为追求质量&#xff0c;所以写的较慢。大概在接下来的三天内会把LinkedList源码解析出完。大概还有两篇文章。废话不多说&#xff0c;正片开始&#xff01; 大家都知道&#xff0c;LinkedList是在Java底层中是由 …

手机上音乐如何转换成MP3格式?分享5款音频格式转换APP

手机上音乐如何转换成MP3格式&#xff1f;相信很多外出办公或者不经常使用电脑的工作人士&#xff0c;学生党&#xff0c;媒体从业者都有这样的疑惑和需求。不同设备和应用可能支持不同的音频格式&#xff0c;导致某些情况下需要将音乐文件转换为MP3格式以确保兼容性。下面&…

操作系统|day4.Linux、Linux内核、Linux负载、Linux文件存储

文章目录 LinuxLinux内核定义功能态 Linux负载定义 Linux文件存储链接分类区别使用场景 拷贝 Linux Linux内核 定义 内核是操作系统的核心&#xff0c;具有很多最基本功能&#xff0c;它负责管理系统的进程、内存、设备驱动程序、文件和网络系统&#xff0c;决定着系统的性能…

.NET周刊【7月第4期 2024-07-28】

国内文章 .NET 高性能缓冲队列实现 BufferQueue https://mp.weixin.qq.com/s/fUhJpyPqwcmb3whuV3CDyg BufferQueue 是一个用 .NET 编写的高性能的缓冲队列实现&#xff0c;支持多线程并发操作。 项目地址&#xff1a;https://github.com/eventhorizon-cli/BufferQueue 项目…

【虚拟仿真】Unity3D中实现2DUI显示在3D物体旁边

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址QQ群:398291828大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 这篇文章来实现2DUI显示在3D物体旁边,当我们需要在3D模型旁边显示2DUI的时候,比如人物的对…

grep工具的使用

grep [options]…… pattern [file]…… 工作方式&#xff1a; grep 在一个或者多个文件中搜索字符串模板&#xff0c;如果模板中包括空格&#xff0c;需要使用引号引起来&#xff0c;模 板后的所有字符串会被看作是文件名。 工作结果&#xff1a;如果模板搜索成功&#xf…

Springboot+Vue在线水果(销售)商城管理系统-附源码与配套论文

1.1 研究背景 互联网概念的产生到如今的蓬勃发展&#xff0c;用了短短的几十年时间就风靡全球&#xff0c;使得全球各个行业都进行了互联网的改造升级&#xff0c;标志着互联网浪潮的来临。在这个新的时代&#xff0c;各行各业都充分考虑互联网是否能与本行业进行结合&#xf…

Java:进程和线程

文章目录 进程线程的概念和区别总结如何创建线程1.继承Thread重写run2.实现Runnable重写run3.继承Thread重写run,通过匿名内部类来实现4. 实现Runnable重写run,通过匿名内部类来实现5.基于lambda表达式来创建 虚拟线程 并发编程: 通过写特殊的代码&#xff0c;把多个CPU核心都利…