「C++」类和对象最终回
目录
前言
初始化列表:
使用及特点:
总结:
案例分析:
类型转换
单参数构造函数:
多参数构造函数:
static成员
友元
内部类
匿名对象
特点
使用方法:
匿名对象使用实例补充:
对象拷贝时的编译器优化
后记
前言
欢迎大家来到小鸥的博客,本篇将带你了解构造函数的初始化列表,构造函数传参时的类型转换,static成员,友元,内部类以及匿名对象等相关内容~

初始化列表:
在前面学习的构造函数实现中,初始化成员变量时使用的都是在函数体内进行赋值的方法,而构造函数还可以通过初始化列表来进行成员变量的初始化。
使用及特点:
1. 初始化列表在函数参数列表后,以一个冒号开始,接着以逗号为分割,每个成员变量后面跟一括号来放初始值或者表达式:
//Date(int year, int month, int day)Date(int year = 1, int month = 1, int day = 1):_year(year)//(year + 1),_month(month),_day(day){}
其中初始化列表的括号中可以是一个表达式;
2. 每个成员变量在初始化列表中只能出现一次,这是因为初始化列表的性质可以认为是成员变量定义初始化的地方,就和函数的声明和定义一样,定义有且只有一个。


3. 引用成员变量,const成员变量,没有默认构造的类类型成员变量,都必须放在初始化列表中进行初始化,否则将会报错
原因:
- 引用在定义时必须指定引用对象(类似指针必须指定指向的地址);
- const修饰的变量必须在定义时赋值,后续也不能通过赋值来修改(const修饰具有常性);
- 类类型的成员变量,定义时会调用默认构造函数,若只存在普通构造函数,又不给参数的话,其定义就会报错,但初始化列表中给它初始值之后,就相当于调用了该类的普通构造函数(传参)
例:


此处的i 和a 就是引用和const成员变量,由于初始化列表的性质类似与定义,所以可以在初始化列表中修改,而不能在函数体中进行修改。
4. C++11后支持在成员变量声明的位置给缺省值,这个缺省值就是为了在当一个成员变量没有显示在初始化列表中时使用。

此时_day成员没有在初始化列表中,也没有在函数体中进行赋值,所以d1对象定义完成后,得到的_day结果为2.
注意
- 成员变量声明时的值是一个缺省值,而不是赋值,即只有既不在初始化列表中,也不在函数体中时,才会使用,和函数的缺省参数性质一样。
- 成员变量声明处的缺省值,和构造函数参数中的缺省值要注意区分,前者是未显示在初始化列表中时使用,而后者是为了构造函数没有传参时使用的。
5. 初始化列表中是按照声明时的顺序进行初始化(因为开空间时的存放顺序就是按照声明的顺序存放的)的,和成员在初始化列表中的先后顺序无关,但建议保持一致。

总结:
(尽量不在函数体中赋值)
- 每个构造函数都有初始化列表;
每个成员变量都会进行初始化列表:
显示写在初始化列表中的成员,直接进行初始化;
不显示写在初始化列表中的成员:
声明时有缺省值就用缺省值;
没有缺省值:
内置类型成员变量:不确定,看编译器,大概率为随机值;自定义类型成员变量:调用它的默认构造,没有则报错;
引用,const修饰,没有默认构造的类类型成员变量,必须显示写在初始化列表中进行初始化。
案例分析:

结果分析:
- 由声明顺序可知,_b先声明,所以先初始化,但由于此时_a还未进行初始化,所以_b初始化结果为零;
- _a初始化使用传值参数a的值进行初始化,所以结果为1;
- 综合可知:声明时成员变量的缺省值只有在对其自身初始化时起作用,_a在作为初始值为_b初始化时,还未进行初始化,所以_b结果为随机值,而不是_a的缺省值
类型转换
C++支持内置类型隐式转换为类类型对象,但要保证自定义类型兼容该内置类型,且类类型中存在兼容该内置类型的构造函数。
在构造函数前加上关键字explicit可以禁止该类型转换
单参数构造函数:
class A
{
public:void Print(){cout << _a << endl;}A(int i = 0):_a(i){}//拷贝构造函数A(const A& pa):_a(pa._a){}
private:int _a;
};class Stack
{
public:void Push(const A& a){//....}
private:A _arr[10];int top;
};int main()
{A aa1(1);//传参给构造函数进行正常构造aa1.Print();A aa3 = aa1;//调用拷贝构造// 隐式类型转换// 2先隐式转换为double,构造出一个A类型的临时对象,再将临时对象拷贝构造到aa2// 编译器中遇到构造+拷贝构造->优化为直接构造A aa2 = 2;aa2.Print();//A& raa2 = aa2;//引用//const A& raa3 = 2;//2类型转换产生临时变量具有常性,所以必须加上const才能引用Stack st;st.Push(aa1);st.Push(3);//int类型转换为A类型return 0;
}
上述代码中,构造函数加上explicit:

多参数构造函数:
class A
{
public:A(int a = 1, int b = 1):_a(a), _b(b){}private:int _a;int _b;
};
class Stack
{
public:void Push(const A& a){//....}
private:A _arr[10];int top;
};
int main()
{A aa1(2, 2);A aa2 = { 2,2 };Stack st1;st1.Push(aa1);st1.Push({ 2,2 });return 0;
}
参数为多个时,类型转换要用大括号括起来。
总结:C++支持隐式类型转换,是借助构造函数来进行的。
static成员
1. static修饰的成员变量,称为静态成员变量,静态成员变量必须在类外进行初始化;

2. 静态成员变量是该类的所有对象共享的,不单独属于某个对象,也不存在对象中,而是存在静态区中,所有对象都可以调用;

3. static修饰成员函数,叫做静态成员函数,静态成员函数不存在this指针;
4. 静态成员函数只能访问其他静态成员函数,由于没有this指针,所以不能访问非静态成员变量;

5. 非静态成员函数,可以随意访问静态成员变量和函数;
6. 静态成员也受public,private,protected访问限定符的限制;
7. 静态成员为public时,可通过 类名::静态成员 和 对象名::静态成员 两种方式来外部访问;

8. 静态成员声明时不能添加缺省值,因为静态成员要在类外部定义初始化,不属于某个对象,而声明时的缺省值是用于初始化列表进行初始化的,静态成员不走构造函数的初始化列表路线。
class A
{
public:static int _b;//开放静态成员,可外部访问static void func(){cout << _a << endl;cout << _b << endl;//cout << _c << endl;//3. 4. 静态成员函数没有this指针,无法调用非静态成员,报错}void Print(){cout << _a << endl;cout << _b << endl;cout << _c << endl;}void Set(int a){_a = a;}
private://1. 8. 声明时的缺省值用于初始化列表,而静态成员不在构造函数中定义,所以不能有缺省值//static int _i = 1;//错误static int _a;//私有静态成员int _c = 0;
};int A::_a = 1;
int A::_b = 1;int main()
{A aa1; //_a _b _caa1.Print();// 1 1 0A aa2;//2. 对象aa2修改静态成员_a后,aa1打印出来_a也随之改变aa2.Set(2); //_a _b _caa1.Print();// 2 1 0A::func();// 2 1aa2.func();return 0;
}
友元
友元分为友元函数和友元类,其提供了一种突破类访问限定符封装的方式,将函数声明或者类声明的前面加上friend关键字,并且将其放到一个类里面,就构成了友元声明。
- 外部友元函数可以访问类的private和protected的成员,友元函数只是一个声明,而不会成为该类的成员函数;
- 友元声明可以在类定义的任何地方声明,不受访问限定符的限制;
- 一个函数可以是多个类的友元函数;
- 友元类中的成员函数都可以是另一个类的友元函数,都可以访问另一个类中的private和protected成员;
- 友元类的关系是单向的,不具有交换性,若A类是B类的友元类,则B类可以访问A类的成员,但B类不是A类的友元类,就不能访问,除非也在B类中加上A类的友元声明;
- 友元关系不具有传递性,如果A类是B类的友元,B类是C类的友元,不代表A类就是C类的友元,而需要单独声明;
- 友元有时提供了一定的便利性,但友元会增加耦合度,破坏封装性,所以友元不宜多用。
class B;class A
{
public://PPrint是A类的友元函数,可以访问其方法和成员friend void PPrint(const A& aa, const B& bb);friend class B;A(char a = 'a', char b = 'a'):_a(a),_b(b){}void PrintA() const{cout << _a << endl;cout << _b << endl;}
private:char _a;char _b;
};
class B
{friend void PPrint(const A& aa, const B& bb);
public:B(char a = 'b', char b = 'b'):_a(a),_b(b){};void PrintB() const{cout << _a << endl;cout << _b << endl;}
private:char _a;char _b;
};
void PPrint(const A& aa, const B& bb)
{//友元可以访问private和protected成员cout << aa._a << endl;cout << bb._b << endl;
}
int main()
{A aa;B bb;PPrint(aa, bb);return 0;
}
内部类
如果一个类定义在另一个类的内部,则这个类成为该类的内部类。
- 内部类是一个独立的类,与定义在全局的类相比,只是受到了类域的限制和访问操作符的限制,所以一个类定义的对象中不会包含其内部类。
- 内部类默认是其外部类的友元类,反之不成立。
- 内部类也是一种封装,当A类和B类紧密关联,A类主要的作用就是为B类服务时,就可以设计为内部类,若放到private和protected中,那么A类就为B类的专属内部类,其它地方将无法使用。
class A
{
public://构造函数A(int a = 1):_a(a){cout << "A(int a = 1)" << endl;}//拷贝构造函数A(const A& aa){cout << "A(const A& aa)" << endl;_a = aa._a;}//析构函数~A(){cout << "~A()" << endl;_a = 0;}void PrintA(){cout << "void PrintA()" << endl;//B()._b;//不能直接调用B类的成员变量,需要友元声明B().PrintB(A());}
private:int _a = 1;//A类的私有内部类class B{public://friend class A;void PrintB(const A& aa){cout << "void PrintB(const A& aa)" << endl;//可以直接调用A类的成员变量,因为内部类默认为外部类的友元类cout << aa._a << endl;}private:int _b;};
};
int main()
{A a1(2);a1.PrintA();return 0;
}
运行结果:

图示结果分析可知,对象a1先构造,然后调用PrintA函数,PrintA函数中创建了一个匿名对象来调用B类中的函数PrintB,所以打印出来的结果为1;
也说明B作为内部类可以直接调用A类的成员变量,是A的友元类,但反之A默认不是B的友元,需要单独声明。
匿名对象
特点
- 用 类型(实参) 的方式定义出来的对象叫做匿名对象,而之前定义对象的方式 类型 对象名(实参) 定义出的对象叫有名对象
- 匿名对象的生命周期只在其所在的一行,当需要定义一个对象临时使用时,就可以定义为匿名对象。
使用方法:
类名().成员函数();
#include <iostream>
using namespace std;class A
{
public:A(int a = 1):_a(a){cout << "A(int a = 1)" << endl;}A(const A& aa){cout << "A(const A& aa)" << endl;_a = aa._a;}~A(){cout << "~A()" << endl;_a = 0;}void Print(){cout << "void Print()" << endl;}
private:int _a = 1;
}int main()
{A().Print();//当前行结束后,匿名对象就会销毁return 0;
}
匿名对象使用实例补充:
万能头文件:<bits/stdc++> 会将常用的头文件一并包含。
- 不建议日常使用,只在竞赛时节省时间时有用。
对象拷贝时的编译器优化
在不影响正确性的前提下,对连续的构造和拷贝构造进行优化合并,从而减少拷贝消耗,提高代码速度

图中aa原本为隐式类型转换,先构造再拷贝构造,但编译器优化为直接构造,从而提升效率。
后记
感谢各位读者的阅读,欸,有不足的地方还是请大家继续指正哈~
本期专栏:C++_海盗猫鸥的博客-CSDN博客
个人主页:海盗猫鸥-CSDN博客
感谢各位的关注~

相关文章:
「C++」类和对象最终回
目录 前言 初始化列表: 使用及特点: 总结: 案例分析: 类型转换 单参数构造函数: 多参数构造函数: static成员 友元 内部类 匿名对象 特点 使用方法: 匿名对象使用实例补充&#…...
ELK:Elasticsearch、Logstash、Kibana Spring Cloud Sleuth和Spring Cloud Zipkin
〇、虚拟机中docker安装elasticsearch 、Kibana、Logstash elasticsearch导入中文分词器 Logstash修改es数据库ip及创建索引名配置 一、elasticsearch数据库的结构 和mysql作比较,mysql中的数据库的二维表相当于es数据库的index索引结构;mysql数据库的二…...
动态规划17:123. 买卖股票的最佳时机 III
动态规划解题步骤: 1.确定状态表示:dp[i]是什么 2.确定状态转移方程:dp[i]等于什么 3.初始化:确保状态转移方程不越界 4.确定填表顺序:根据状态转移方程即可确定填表顺序 5.确定返回值 题目链接:123.…...
华为OD机试真题---预定酒店
华为OD机试真题中的“预定酒店”题目是一道典型的算法题,主要考察的是如何在给定的酒店价格数组中找到最接近心理价位的k个酒店,并按价格从低到高输出。以下是对该题目的详细解析: 一、题目描述 放暑假了,小明决定到某旅游景点游…...
力扣242.有效的字母异位词
题目链接:242. 有效的字母异位词 - 力扣(LeetCode) 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的 字母异位词。 示例 1: 输入: s "anagram", t "nagaram"输出: true 示例 2: 输入: s &q…...
Android IP路由策略和防火墙
Android IP路由策略和防火墙 Platform: RK3368 OS: Android 6.0 Kernel: 3.10.0 文章目录 Android IP路由策略和防火墙ip route, ip rule, iptables简介ip routeip ruleiptables Android路由策略Android路由策略优先级命令查看当前路由策略 Android路由表命令查看路由表命令…...
MySQL insert ... select 语句锁表导致数据写不进去
问题现象 调用后台接口向表 t1 insert 写入数据时一直等待直到超时,猜测表 t1 被其它事务加锁了没有释放。 问题分析 在发生死锁时,通过执行下面命令查看事务和锁信息: select * from information_schema.INNODB_TRX 用来查看正在运行的事…...
Android摄像头Camera2和Camera1的一些总结
Android 系统对摄像头的同时使用有限制,不能同时使用摄像头进行预览或者录制音视频。 例如:界面上有两个SurfaceView, 这两个SurfaceView不能同时预览或者录制音视频,只能有一个正常工作(一个SurfaceView预览前置摄像头ÿ…...
【Linux 从基础到进阶】Linux中的用户认证与授权
Linux中的用户认证与授权 1. 引言 在Linux系统中,**用户认证(authentication)和授权(authorization)**是两个核心的安全机制,用来控制系统资源的访问和管理用户操作权限。用户认证确保登录的用户是合法的…...
用户界面设计:视觉美学与交互逻辑的融合
1、什么是用户界面 用户界面(UI)是人与机器之间沟通的桥梁,同时也是用户体验(UX)的重要组成部分。用户界面设计包括两个核心要素:视觉设计(即产品的外观和感觉)和交互设计ÿ…...
ZK集群搭建:详细步骤与注意事项
在大数据和分布式系统日益重要的今天,ZooKeeper(简称ZK)作为一种分布式协调服务,扮演着举足轻重的角色。它主要用于管理大型分布式系统中的配置信息、命名、同步等。下面将详细介绍如何搭建一个ZooKeeper集群,帮助大家…...
如何将csdn文章导出为pdf
前言 在csdn上浏览文章的时候我发现有的文章支持pdf导出,但是有的文章不支持pdf导出,为了解决能将csdn上所有文章都能以pdf格式导出遂作此文。 正文 先上代码: (function(){use strict;var contentBox $("div.article_content")…...
【艾思科蓝】Imagen:重塑图像生成领域的革命性突破
【连续七届已快稳ei检索】第八届电子信息技术与计算机工程国际学术会议(EITCE 2024)_艾思科蓝_学术一站式服务平台 更多学术会议请看 学术会议-学术交流征稿-学术会议在线-艾思科蓝 目录 引言 一、Imagen模型的技术原理 1. 模型概述 2. 工作流程 …...
java类和对象(下): 封装 static成员 内部类
前言: 在前期的知识点中,我们学习了java中this函数的使用和相关的概念。这期我们将介绍封装的概念,以及常见内部类的使用,让我们开车吧!!!! 本期目录: 6. 封装 7. st…...
外包干了3周,技术退步太明显了。。。。。
先说一下自己的情况,大专生,21年通过校招进入武汉某软件公司,干了差不多3个星期的功能测试,那年国庆,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我才在一个外包企业干了3周的功…...
VIVO算法题——数位之积
记录算法究极无敌菜菜菜鸟的垃圾思维 题目: 现给定任意正整数 n,请寻找并输出最小的正整数 m(m>9),使得 m 的各位(个位、十位、百位 … …)之乘积等于n,若不存在则输出 -1。 菜鸟…...
OPC Router快速打通设备层与influxDB数据通讯
随着时代演化,数据量呈几何倍数增加的情况下出现了时序数据库。时序数据库是基于时间进行存储的数据库,每一条数据中都有一个时间戳,这种数据库特别适合存储那些随着时间变化的数据,通过一些工具处理后,能够分析出数据…...
鸿蒙开发 四十四 ArkTs BuilderParam传递UI(二)
子组件多个BuilderParam,必须通过参数的方式传入,如果界面中有多个界面需要传递,可以定义多个尾随闭包,如图: 在自定义组件中调用: 在使用时候调用是作为参数传递给自定义的组件,参数是界面&…...
同期数分析-留存率
目录 同期数分析 加载数据 单月实现 统计每个月的订单量 求2月份的订单量和用户数量 求2月之前的历史订单量 筛选出2023年2月的新增的用户数 计算2023年2月在后面的留存情况 完整的2023年2月份同期群结果 遍历合并和分析 引入月份列表 遍历 调整成留存率的形式 回…...
Java前后端交互:构建现代Web应用
在现代Web应用开发中,前后端分离是一种常见的架构模式。后端通常负责数据处理和业务逻辑,而前端则负责用户界面和用户体验。Java作为后端开发的强大语言,提供了多种方式与前端进行交互。本文将探讨Java后端与前端交互的几种主要方式ÿ…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...

自定义类型成员变量: