「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后端与前端交互的几种主要方式ÿ…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...

Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...