c++初阶------类和对象(下)
作者前言
🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂
🎂 作者介绍: 🎂🎂
🎂 🎉🎉🎉🎉🎉🎉🎉 🎂
🎂作者id:老秦包你会, 🎂
简单介绍:🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂
喜欢学习C语言、C++和python等编程语言,是一位爱分享的博主,有兴趣的小可爱可以来互讨 🎂🎂🎂🎂🎂🎂🎂🎂
🎂个人主页::小小页面🎂
🎂gitee页面:秦大大🎂
🎂🎂🎂🎂🎂🎂🎂🎂
🎂 一个爱分享的小博主 欢迎小可爱们前来借鉴🎂
类和对象
- **作者前言**
- 类的构造函数
- 初始化列表
- static成员
- 静态成员
- 静态成员函数
- explicit关键字
- 单参数的隐式类型转换
- 多参数类型的隐式类型转换(c++11后支持)
- 友元
- 友元函数
- 友元类
- 内部类
- 扩展
- 拷贝小误区
- 构造优化(编译器的优化)
类的构造函数
前面我们学习了类的构造函数的定义,如下:
这个就是我们之前写的构造函数的定义,叫做函数体内初始化,除了这样定义,还有另外一种定义叫初始化列表
初始化列表
使用这个主要是为了解决一些类型无法初始化
- 类中的引用无法初始化
可以看到使用函数体内初始化引用时是无法初始化引用变量的,因为在类中的成员是声明,在函数内才是定义(创建对象),const 也要在定义时初始化,为了解决引用和const在类的成员函数里面初始化不了,就有了初始化列表,
初始化列表,初始化列表以冒号开头,后跟一系列以逗号分隔的初始化字段
Date()//初始化列表:_a(d1._a),_b(30){//函数体内定义_year = d1._year;_month = (d1._month);_day = (d1._day);}
这里是一个类的默认构造函数,
- 假设初始化列表没有写内置类型的定义和函数体内定义也没有,内置类型就是随机值(编译器定义的)
- 如果类的成员有自定义类型,没有在初始化列表定义,自定义类型会自动调用它本身的默认构造函数。
无参的构造函数和全缺省的构造函数以及编译器自己生成的都称为默认构造函数
(不用传参的构造函数)
namespace naco
{class D{public://默认构造D(int a = 20){_a = 20;}private:int _a;};class Date{public:Date(int year, int month, int day)//初始化列表:_a(year), _b(30),A(20)//不想调用自己默认值默认构造,就传值{//函数体内定义_year = year;_month = (month);_day = (day);}~Date(){cout << _year << "-" << _month << "-" << _day << endl;}private://声明int _year;int _month;int _day;int& _a;const int _b;D A;};
}
我们还可以在声明的时候定义,这样就可以哪怕初始化列表不写,也不会报错
class Date{public:Date(int year, int month, int day)//初始化列表:_a(year),A(20){//函数体内定义_year = year;_month = (month);_day = (day);}~Date(){cout << _year << "-" << _month << "-" << _day << endl;}private://声明int _year;int _month;int _day;int& _a;const int _b = 100;D A;//自定义类型};
所以可以总结一下:
初始化列表主要针对三类
- 引用
- const修饰的变量
- 没有默认构造函数的自定义类型成员,有默认构造的对象,哪怕没有定义也会调用自己的默认构造,或者是不使用默认值的自定义类型成员
建议:
- 构造函数由初始化列表和函数体构成,缺一不可,
- 每个成员只能再初始化列表出现一次,但是不会影响函数体内初始化,在函数体内还可以出现
- 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关建议类中声明次序和初始化顺序一样
class A
{
public:A(int a):_a1(a),_a2(_a1){}void Print() {cout<<_a1<<" "<<_a2<<endl;}
private:int _a2;int _a1;
};
int main() {A aa(1);aa.Print();
}
结果是1和随机值,先初始化_a2,然后再初始化_a1
,
static成员
静态成员
声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化,
例子:
写出一个类,计算出一个程序中的类对象有多少个
class A
{
public:A(int a = 20){_a = a;++count;}A(const A& d1){_a = d1._a;++d1.count;}~A(){--count;}void Print(){cout << count << endl;}private://shngmstatic int count;//属于全部对象共同使用的.不会每个对象都有专属的count,而是全部对象公用这个countint _a;};
//静态成员定义
int A::count = 0;
int main()
{A a(10);A b(30);a.Print();return 0;
}
静态成员函数
- 在main函数之前就初始化了.而不是创建对象后才初始化,
- 只是放到类中,属于类的私有成员,
- 静态成员是全局的,所有对象共用,
- 静态成员只能在类外面定义,不属于类外访问,不能走构造函数的路
静态成员访问形式:
A aa;
A::count;
aa.count;
//这两种都可以访问,
可能有些小可爱觉得不太方便,就会使用一下匿名对象,这个匿名对象和C语言的匿名结构体是不一样的,匿名对象的生命周期只是在一行中
class A
{
public:A(int a = 20){_a = a;++count;}A(const A& d1){_a = d1._a;++d1.count;}~A(){--count;}void Print(){cout << A::count << endl;}private://shngmstatic int count;int _a;};
//定义
int A::count = 0;
int main()
{A().Print();//A()是一个匿名对象,生命周期在这一行,出了这一行,这个匿名对象就会被析构return 0;
}
A()就是匿名对象,生命周期在定义的那一行中,
静态成员函数
特点:没有this指针
调用静态成员函数和调用静态成员的方法是一样的,
可以自定义类型::静态成员函数和对象.静态成员函数调用
注意: 静态成员函数可以直接调用静态成员
作用
- 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区
- 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明
- 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问
- 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
- 静态成员也是类的成员,受public、protected、private 访问限定符的限制
- 静态成员可以在类中直接使用,
explicit关键字
单参数的隐式类型转换
class A
{
public:A(int a = 20):_a(a){}A(const A& d1){_a = d1._a;}~A(){cout << _a << endl;}
private:int _a;
};
int main()
{A tes = 20;return 0;
}
上面代码涉及到了内置类型对象隐式转换成自定义类型对象
需要注意的是支持这个方式是要构造函数的参数只有一个int类型参数(this不包含在内),前面我们知道这个临时变量具有常性,需要用const修饰的变量来接收,
能隐式互相转的内置类型是整形(int)和浮点数,这里两种对是类型相近的,表示数据的大小。
内置类型转自定义类型的话,前提是自定义类型的构造函数必须是单参数构造函数
还有就是全缺省构造函数。和只有一个参数没有默认值的半缺省构造函数,都可以隐式转化
简单的理解就是只能传一个参数的构造函数可以
多参数类型的隐式类型转换(c++11后支持)
上面是只能传一个参数的隐式转换,如果是多参数的话可以这样
class A
{
public:A(int a , int b = 20, int c=30):_a(a),_b(b),_c(c){}A(const A& d1){_a = d1._a;_b = d1._b;_c = d1._c;}~A(){cout << _a << endl;}
private:int _a;int _b;int _c;};
int main()
{A tes = {30, 20 ,10};const A& test = {60, 50, 10};//引用的是A(60,50,10)的临时变量return 0;
}
这里是要在c++11后才支持的,多参数的类型转换,一样的道理,
为了防止这些转换,cpp就有了一个explicit关键字
使用这个关键字来修饰构造函数就会防止有隐式转换了
友元
友元分为:友元函数和友元类
友元函数
友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。定义在外面就不要friend,
class A
{
public:A(int a , int b = 20, int c=30):_a(a),_b(b),_c(c){}A(const A& d1){_a = d1._a;_b = d1._b;_c = d1._c;}~A(){cout << _a << endl;}//友元函数(不是任何类的成员函数)friend std::ostream& operator<<(std::ostream& out, const A& d1);private:int _a;int _b;int _c;
};
std::ostream& operator<<(std::ostream& out, const A& d1)
{out << d1._a << d1._b << d1._c;//访问了类的私有成员,没有this指针return out;
}
特征
-
友元函数可访问类的私有和保护成员,但不是类的成员函数
-
友元函数不能用const修饰
-
友元函数可以在类定义的任何地方声明,不受类访问限定符限制
-
一个函数可以是多个类的友元函数
-
友元函数的调用与普通函数的调用原理相同
友元类
class A
{public:friend class B;A(int a, int b = 20, int c = 30):_a(a), _b(b), _c(c){}A(const A& d1){_a = d1._a;_b = d1._b;_c = d1._c;}~A(){cout << _a << endl;}private:int _a;int _b;int _c;
};
class B
{
public:B(int a = 20, int b = 30, int c = 40, int Ba = 50, int Bb = 60, int Bc = 70):t(a,b,c),_Ba(Ba),_Bb(Bb),_Bc(Bc){}void Print(){cout << t._a << " " << t._b << " " << t._c << endl;//直接访问t的私有成员}~B(){cout << "B析构了" << endl;}private:int _Ba;int _Bb;int _Bc;A t;
};
int main()
{B te = 50;te.Print();return 0;
}
特征
- 友元关系是单向的,不具有交换性。(友元类可以访问普通类的私有成员或者成员函数,前提是普通类声明过这个友元类)
- 友元关系不能传递(C是B的友元类,B是A的友元类,但是C不是A的友元类)
- 友元关系不能继承
内部类
如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,
它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越
的访问权限。
注意:内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访
问外部类中的所有成员。但是外部类不是内部类的友元。
如果内部类被public,可以在类外面进行定义,需要使用 外部类名:: 内部类,否则的话只能在外部类内定义使用,
class A
{
public:A(int a, int b, int c):bb(20){_a = a;_b = b;_c = c;}
private:class B{public:B(int b){_bb = b;}~B(){A aa(30,40,50);aa._a++;aa._b++;aa._c++;}private:int _bb;};private:int _a;int _b;int _c;B bb;//内部类
};
int main()
{A aa(1,1,1);//A::B bb(1);//内部类被oublic可以使用return 0;
}
特性:
- 内部类可以定义在外部类的public、protected、private都是可以的。
- 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。
扩展
拷贝小误区
class A
{
public:A(int a = 10){_a = a;}A(const A& d){_a = d._a;}
private:int _a;
};
int main()
{A a1;A a2 = a1;//拷贝A a3(20);a1 = a3;//赋值return 0;
}
- 一个存在的对象拷贝构造另一个要创建的对象,就是拷贝构造
- 两个存在的对象使用=就是赋值
构造优化(编译器的优化)
随着时代的变迁,编译器对于一些代码优化了很好,比如构造函数
在同一个表达式中,连续的构造+构造/ 构造+拷贝构造/拷贝构造+拷贝构造合二为一
红框中的大概意思就是,用1构造一个临时对象,然后用这个临时对象拷贝构造a4,但是结果却是调用了构造函数,所以就会有一个结论:
构造 + 构造=>构造
拷贝构造+构造=>构造
拷贝构造 + 拷贝构造=>拷贝构造
不同的编译器优化成度不同,但是普遍有正常的优化,有一些编译器优化可能是多个表达式优化
比如VS2019:
Linux下的g++编译器
就可以看出差别,不同的编译器优化的程度会不同。
相关文章:

c++初阶------类和对象(下)
作者前言 🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂 🎂 作者介绍: 🎂🎂 🎂 🎉🎉🎉…...

PMP考试:如何高效学习PMBOK?
PMBOK(项目管理知识体系指南)是PMP考试的核心教材,学习PMBOK对于备考PMP考试至关重要。那么我将分享一些高效学习PMBOK的方法和技巧,帮助同学们更好地掌握项目管理知识。 一、制定学习计划 在学习PMBOK之前,制定一个详…...

个人博客网站前端页面的实现
博客网站前端页面的实现 博客登录页 相关代码 login.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><…...
Kotlin Retrofit 网络请求
一、添加依赖: //Retrofit 网络请求implementation("com.squareup.retrofit2:retrofit:2.3.0")implementation("com.squareup.retrofit2:converter-gson:2.3.0")//json转换 二、创建单例类: package com.example.buju.httpimport …...
pyside6 pytq PyDracula QVideoWidget视频只有声音没有画面
解决方案: 先不使用框架,纯pyside6代码,如果添加视频有画面有声音,那可以排除是硬件问题,如果没有画面只有声音,可能是视频解码器无法解码,换个格式的视频文件如果只有使用PyDracula 出问题&am…...
Python爬网页,不确定网页的编码,不需要用第三方库
Python爬网页,不确定网页的编码,不需要用第三方库,自己写个判断,乱拳打死老师傅 detect试了,不好用 apparent_encoding试了,不好用 encoding试了,不好用 headers里get试了,不好用…...

Web测试的基础流程(外加测试过程需要的注意5点)
前言 在Web工程过程中,基于Web系统的测试、确认和验收是一项重要而富有挑战性的工作。基于Web的系统测试与传统的软件测试不同,它不但需要检查和验证是否按照设计的要求运行,而且还要测试系统在不同用户的浏览器端的显示是否合适。 重要的是…...

项目解决方案:视频监控接入和录像系统设计方案(下)
目 录 1.概述 2. 建设目标及需求 2.1建设总目标 2.2 需求描述 2.3 需求分析 3.设计依据与设计原则 3.1设计依据 3.2 设计原则 4.建设方案设计 4.1系统方案设计 4.2组网说明 5.产品介绍 5.1视频监控综合资源管理平台介绍 5.2视频录像服务器和存储 5.2.…...
Python爬虫-使用Prefect框架实现一个可视化爬虫项目
前言 本文是该专栏的第19篇,后面会持续分享python爬虫干货知识,记得关注。 相信有的同学,在处理爬虫项目的时候,有时也会需要你将爬虫项目进行一个可视化展示,方便管理者能及时详细的了解当前爬虫任务的执行进度以及执行情况,甚至需要做一个爬虫监控预警的可视化任务。 …...
[hive面试真题]-基础理论篇
hive的工作流程 hive中分区表,分桶表 工作中hive分区表的应用示例 发现hive分区中的数据不对怎么处理 hive出现code 1 2 3 什么原因 ,怎么处理 工作中hive常见的文件格式 .压缩格式 工作时常用的hive函数 谈谈对窗口函数的理解 hive中如果出现数据倾斜 ,怎么发现 ,怎么…...
【其他】sd卡的照片在相机上能看到在电脑上却看不到
sd卡的照片在相机上能看到在电脑上却看不到 前情提要:太长不看版解决办法:思路:一、首先考虑恢复数据二、 解决文件后缀是exe的问题 前情提要: 在相机里可以看到照片和视频,但是SD卡通过读卡器插入电脑看不到&#x…...

Linux 之六:系统性能监控和挂载
系统性能 Linux系统中,有许多命令用于监测和分析性能指标。以下是一些常用的Linux性能分析命令: top:实时查看并监控CPU、内存以及各个进程的资源占用情况。htop(需要安装):一个增强版的 top 命令&#x…...

【Web】浅聊Java反序列化之C3P0——JNDI注入利用
目录 简介 原理分析 EXP 前文:【Web】浅聊Java反序列化之C3P0——URLClassLoader利用 【Web】浅聊Java反序列化之C3P0——不出网Hex字节码加载利用 简介 出网的情况下,这个C3P0的Gadget可以和fastjson,Snake YAML , JYAML,Yamlbeans , …...

Java项目:基于Springboot+vue实现的付费自习室系统设计与实现(源码+数据库+毕业论文)附含微信小程序端代码
一、项目简介 本项目是一套基于Springbootvue实现的付费自习室系统 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,eclipse或者idea 确保可以运行! 该系统功能完善、界面美观、操作简单、…...

C++写食堂菜品管理系统
说明:本博文来自CSDN-问答板块,题主提问。 需要:学校拟开发一套食堂菜品管理系统,以便对菜品和同学们的评价进行管理,其中包含如下信息: 商户:商户名称、柜面位置、电话…… 菜品:菜品编号、菜品名称、价格、所属商户…… 学生:注册账号、昵称、电话…… 食堂里的商户…...

vue 在线预览word
1 mammoth 先找的是mammoth这个插件yarn add mammoth,版本是1,7.0 参考网上的示例使用如下: import mammoth from "mammoth"; const vHtml ref("") const readExcelFromRemoteFile (url) >{var xhr new XMLHttpRequest();xhr.open("…...

七彩虹八渐变 外贸建站公司wordpress模板
进出口水果wordpress外贸模板 漂亮水果wordpress外贸模板,做水果进出品生意的外贸公司自建站官网模板。 https://www.jianzhanpress.com/?p3516 玩具wordpress外贸模板 简洁玩具wordpress外贸模板,适合做跨境电商外贸公司使用的wordpres外贸s网站主题…...
[C++] C++生成随机数
一、简介 在C语言中常使用srand()random()的方式生成随机数,该方式并不是一个很好的随据说生成方法,一方面是因为其生成的随机数质量较低,另一方面其随机数范围也有所限制。在C11中推荐使用随机数引擎的方式生成随机数。 如何高效得生成高质…...

web开发——前端html、css、JavaScript学习总结(持续更新中.......)
目录模版 1 html:结构标签/属性文本标记: mark文本设置:删除线del / 下划线ins/ 加粗b / 强调的文本em / 重要的文本 strong超链接: a联系信息: addressdiv 定义文档中的分区或节: div行元素:spanhtml结构: main / section / articlenav表格:table html中各种标签/属性的英文扩…...
LeetCode 2044.统计按位或能得到最大值的子集数目
给你一个整数数组 nums ,请你找出 nums 子集 按位或 可能得到的 最大值 ,并返回按位或能得到最大值的 不同非空子集的数目 。 如果数组 a 可以由数组 b 删除一些元素(或不删除)得到,则认为数组 a 是数组 b 的一个 子集…...

RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...

Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...

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

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...