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

C++初阶——类和对象(下)

目录

1、再探构造函数——初始化列表

2、类型转换

3、static成员

4、友元

5、内部类

6、匿名对象

7、对象拷贝时编译器的优化(了解)


1、再探构造函数——初始化列表

1. 构造函数初始化除了使用函数体内赋值还有一种方式——初始化列表

初始化列表的使用方式是以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个初始值或表达式

2. 每个成员变量都要走初始化列表,并且在初始化列表中只能出现一次

3. C++11支持在成员变量声明的位置给缺省值,这个缺省值主要是给没有显示在初始化列表初始化的成员使用的

4. C++规定,const成员变量没有默认构造的类类型成员变量必须在初始化列表中 显示初始化或者用缺省值初始化引用成员变量,必须在初始化列表中 显示初始化,否则会编译报错,

由于这三个是定义的时就要求初始化,

所以语法上初始化列表可以认为是每个成员变量定义初始化的地方。

注意:实际上对象在定义时成员变量空间就已经开好了,构造函数只是初始化,不是开空间。

5. 推荐使用初始化列表初始化,因为那些你不在初始化列表初始化的成员变量也会先走初始化列表,

6. 初始化列表按成员变量在类中声明顺序进行初始化,跟成员在初始化列表出现的的先后顺序无关。建议声明顺序和初始化列表顺序保持一致

7. 无论是否显示写初始化列表,每个构造函数都有初始化列表

无论是否在初始化列表显示初始化,每个成员变量都要走初始化列表初始化

#include<iostream>
using namespace std;class Time
{
public:Time(int hour):_hour(hour){cout << "Time()" << endl;}
private:int _hour;
};class Date
{
public:Date(int& x, int year = 1, int month = 1, int day = 1):_year(year), _month(month), _day(day)//, _t(12)//, _ref(x)//, _n(1){// error C2512: “Time”: 没有合适的默认构造函数可用// error C2530 : “Date::_ref” : 必须初始化引用// error C2789 : “Date::_n” : 必须初始化常量限定类型的对象}void Print() const{cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;Time _t;       // 没有默认构造的类类型成员变量int& _ref;          // 引用成员变量const int _n;   // const成员变量
};int main()
{int i = 0;Date d1(i);d1.Print();return 0;
}
#include<iostream>
using namespace std;class Time
{
public:Time(int hour):_hour(hour){cout << "Time()" << endl;}
private:int _hour;
};class Date
{
public:Date():_month(2){cout << "Date()" << endl;}void Print() const{cout << _year << "-" << _month << "-" << _day << endl;}
private:// 注意这里不是初始化,这里给的是缺省值,这个缺省值是给初始化列表用的// 如果初始化列表没有显示初始化,默认就会用这个缺省值初始化int _year = 1;int _month = 1;int _day;Time _t = 1;const int _n = 1;int* _ptr = (int*)malloc(12);
};
int main()
{Date d1;d1.Print();return 0;
}

#include<iostream>
using namespace std;
class A
{
public:A(int a):_a1(a),_a2(_a1){}void Print() {cout << _a1 << " " << _a2 << endl;}
private:int _a2 = 2;int _a1 = 2;
};int main()
{A aa(1);aa.Print();
}

答案:D,1   随机值,  初始化列表按成员变量声明顺序初始化

2、类型转换

1. C++支持内置类型 隐式类型转换为 类类型对象,需要有相关内置类型为参数的构造函数

2. 构造函数前加explicit不再支持隐式类型转换

3. 类类型的对象之间也可以隐式转换,需要有相应的构造函数

#include<iostream>
using namespace std;class A
{
public:// explicit构造函数,就不再支持隐式类型转换// explicit A(int a1)A(int a1):_a1(a1){ }//explicit A(int a1, int a2)A(int a1, int a2):_a1(a1), _a2(a2){ }void Print(){cout << _a1 << " " << _a2 << endl;}int Get() const{return _a1 + _a2;}
private:int _a1 = 1;int _a2 = 2;
};class B
{
public:B(const A& a):_b(a.Get()){ }
private:int _b = 0;
};
int main()
{// 1构造一个A的临时对象,再用这个临时对象拷贝构造aa1// 编译器遇到连续构造+拷贝构造->优化为直接构造A aa1 = 1;aa1.Print();// aa2是临时对象的别名,此时临时对象的生命周期也随之改变const A& aa2 = 1;// C++11之后才支持多参数转化A aa3 = { 2,2 };// aa3隐式类型转换为b对象// 原理跟上面类似B b = aa3;const B& rb = aa3;return 0;
}

3、static成员

1. 用static修饰的成员变量,称之为静态成员变量,静态成员变量一定要在类外进行初始化

2. 静态成员变量属于类而不是属于类的对象的共享数据,不存在对象中,存放在静态区

3. 用static修饰的成员函数,称之为静态成员函数属于类,而不是对象

4. 静态成员函数中可以访问其他的静态成员,但是不能访问非静态的,因为没有this指针。

5.非静态的成员函数可以访问任意的静态成员变量和静态成员函数

6. 在类外,可以通过类名::静态成员或者对象.静态成员来访问静态成员变量和静态成员函数。

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

8. 静态成员变量不能声明位置给缺省值初始化,因为静态成员变量不属于某个对象不走构造函数初始化列表

// 实现⼀个类,计算程序中创建出了多少个类对象?
#include<iostream>
using namespace std;
class A
{
public:A(){++_scount;}A(const A& t){++_scount;}~A(){--_scount;}static int GetACount(){return _scount;}
private:// 类里面声明static int _scount;
};
// 类外面初始化
int A::_scount = 0;int main()
{cout << A::GetACount() << endl; // 0A a1, a2;A a3(a1);cout << A::GetACount() << endl; // 3cout << a1.GetACount() << endl; // 3// 编译报错:error C2248 : “A::_scount” :无法访问private成员(在“A”类中声明)//cout << A::_scount << endl;return 0;
}

求1+2+3+...+n_牛客题霸_牛客网

class Sum
{
public:Sum(){_sum += _i;++_i;}static int GetSum(){return _sum;}
private:static int _i;static int _sum;
};int Sum::_i = 1;
int Sum::_sum = 0;class Solution {public:int Sum_Solution(int n) {Sum a[n];return Sum::GetSum();}
};

4、友元

1. 友元提供了一种突破类访问限定符封装的方式,

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

函数声明或者类声明加friend,并将其放到一个类中

2. 外部友元函数可访问类的私有保护成员,友元函数仅仅是一种声明,不是类的成员函数

3. 友元函数可以在类定义的任何地方声明不受类访问限定符限制

4. 一个函数可以是多个类的友元函数

5. 友元类中的成员函数都可以是另一个类友元函数,都可以访问另一个类中的私有保护成员

6. 友元类的关系单向的,不具有交换性,比如A类是B类的友元,但是B类不是A类的友元。

7. 友元类关系不能传递,如果A是B的友元,B是C的友元,但是A不是C的友元。

8. 有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用

#include<iostream>
using namespace std;// 前置声明,否则A的友元函数声明编译器不认识B
class B;class A
{// 友元声明friend void func(const A& aa, const B& bb);
private:int _a1 = 1;
};class B
{// 友元声明friend void func(const A& aa, const B& bb);
private:int _b1 = 3;
};void func(const A& aa, const B& bb)
{cout << aa._a1 << endl; //  1cout << bb._b1 << endl; //  3
}int main()
{A aa;B bb;func(aa, bb);return 0;
}
#include<iostream>
using namespace std;class A
{// 友元声明friend class B;
private:void F() const{cout << "F" << endl;}int _a1 = 1;
};class B
{
public:void func1(const A& aa){cout << aa._a1 << endl; // 1aa.F(); // Fcout << _b1 << endl; // 3}
private:int _b1 = 3;
};int main()
{A aa;B bb;bb.func1(aa);return 0;
}

5、内部类

1. 如果一个类定义在另一个类的内部,这个内部的类就叫做内部类

内部类是一个独立的类,跟定义在全局相比,他受外部类类域限制访问限定符限制,所以外部类定义的对象中不包含内部类

2. 内部类默认是外部类的友元类,可以访问私有保护成员外部类无法访问内部类的私有成员

3. 内部类本质也是一种封装,当A类跟B类紧密关联,A类实现出来主要就是给B类使用,那么可以考虑把A类设计为B的内部类,如果放到private/protected位置,那么A类就是B类的专属内部类,其 他地方都用不了。

#include<iostream>
using namespace std;class A
{
public:class B // B默认就是A的友元{public:void foo(const A& a){cout << _k << endl;          // 1 OKcout << a._h << endl;        // 1 OK}};
private:static int _k;int _h = 1;
};int A::_k = 1;int main()
{// sizeof是当创建这个类型的一个对象(或变量)的时候,需要为它分配的空间的大小// sizeof会忽略static成员变量的大小cout << sizeof(A) << endl; // 4,A::B b;A aa;b.foo(aa);return 0;
}

求1+2+3+...+n_牛客题霸_牛客网

class Solution {
// 私有的内部类,专属
private:class Sum {public:Sum() {_sum += _i;++_i;}};
public:int Sum_Solution(int n) {Sum a[n];return _sum;}
private:static int _i;static int _sum;
};int Solution::_i = 1;
int Solution::_sum = 0;

6、匿名对象

1. 用类型(实参)定义出来的对象叫做匿名对象,相比之前我们定义的类型对象名(实参)定义出来的 叫有名对象。

2. 匿名对象生命周期只在当前一行,一般临时定义一个对象当前用一下的话,就可以定义匿名对象。

#include<iostream>
using namespace std;class A
{
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}~A(){cout << "~A()" << endl;}
private:int _a;
};class Solution {
public:int Sum_Solution(int n) {//...return n;}
};int main()
{A aa1;// 不能这么定义对象,因为编译器无法识别是⼀个函数声明,还是对象定义//A aa1();// 但是我们可以这么定义匿名对象,匿名对象的特点不用取名字,// 但是他的生命周期只有这一行,我们可以看到下一行他就会自动调用析构函数A();A(1);A aa2(2);// 匿名对象在这样场景下就很好用,当然还有一些其他使用场景,这个我们以后遇到了再说// 匿名对象Solution()Solution().Sum_Solution(10);return 0;
}

7、对象拷贝时编译器的优化(了解)

1. 现代编译器会为了尽可能提高程序的效率,在不影响正确性的情况下尽可能减少一些传参和传返回值的过程中可以省略的拷贝

2. 如何优化C++标准并没有严格规定,各个编译器会根据情况自行处理。当前主流的相对新一点的编译器对于连续一个表达式步骤中的连续拷贝会进行合并优化,有些更新更"激进"的编译器还会进行跨行跨表达式的合并优化。

相关文章:

C++初阶——类和对象(下)

目录 1、再探构造函数——初始化列表 2、类型转换 3、static成员 4、友元 5、内部类 6、匿名对象 7、对象拷贝时编译器的优化(了解) 1、再探构造函数——初始化列表 1. 构造函数初始化除了使用函数体内赋值&#xff0c;还有一种方式——初始化列表&#xff0c; 初始化列…...

趋势洞察|AI 能否带动裸金属 K8s 强势崛起?

随着容器技术的不断成熟&#xff0c;不少企业在开展私有化容器平台建设时&#xff0c;首要考虑的问题就是容器的部署环境——是采用虚拟机还是物理机运行容器&#xff1f;在往期“虚拟化 vs. 裸金属*”系列文章中&#xff0c;我们分别对比了容器部署在虚拟化平台和物理机上的架…...

idea初始化设置

下载idea&#xff1a; https://www.jetbrains.com/idea/ 安装idea 安装插件&#xff1a; Rainbow BracketsLombokMybatisXSonarLintMaven HelperCodeGeeX&#xff08;国内AI插件可用&#xff09; 设置idea注释模板&#xff1a; 设置代码注释模板&#xff1a; https://blo…...

LINUX系统编程之——环境变量

目录 环境变量 1、基本概念 2、查看环境变量的方法 三、查看PATH环境变量的內容 1&#xff09;不带路径也能运行的自己的程序 a、将自己的程序直接添加到PATH指定的路径下 b、将程序所在的路径添加到PATH环境中 四、环境变量与本地变量 1、本地变量创建 2、环境变量创…...

健康老龄化:适合老年人的播客

什么是播客 什么是播客&#xff1f;好问题。对于那些还不熟悉这个术语的人来说&#xff0c;播客有点像在线广播或电视节目。这是一个可下载、可流式传输的程序&#xff0c;定期发布剧集&#xff0c;时长从几分钟到一个多小时不等。您可以在计算机、智能手机或平板电脑上…...

家庭智慧工程师:如何通过科技提升家居生活质量

在今天的数字化时代&#xff0c;家居生活已经不再只是简单的“住”的地方。随着物联网&#xff08;IoT&#xff09;、人工智能&#xff08;AI&#xff09;以及自动化技术的快速发展&#xff0c;越来越多的家庭开始拥抱智慧家居技术&#xff0c;将他们的家变得更加智能化、便捷和…...

Milvus概念

非结构化数据、嵌入和 Milvus 非结构化数据&#xff08;如文本、图像、音频&#xff09;格式多样&#xff0c;蕴含丰富的语义信息&#xff0c;使其分析变得复杂。为了管理这种复杂性&#xff0c;嵌入技术被用来将非结构化数据转换为数值向量&#xff0c;这些向量能够捕捉数据的…...

为什么调用 setState 而不是直接改变 state

在React中&#xff0c;调用setState方法而不是直接改变state的原因涉及多个方面&#xff0c;包括性能优化、状态管理的可预测性、React的设计理念等。以下是对这些原因的详细解释&#xff1a; 1. 性能优化 异步更新与批量处理&#xff1a;setState是异步执行的&#xff0c;Rea…...

【Python爬虫五十个小案例】爬取豆瓣电影Top250

博客主页&#xff1a;小馒头学python 本文专栏: Python爬虫五十个小案例 专栏简介&#xff1a;分享五十个Python爬虫小案例 &#x1fab2;前言 在这篇博客中&#xff0c;我们将学习如何使用Python爬取豆瓣电影Top250的数据。我们将使用requests库来发送HTTP请求&#xff0c;…...

cocos creator 3.8 物理碰撞器Collider+刚体RigidBody 8

遇到一个朋友&#xff0c;你来就行的朋友&#xff0c;我过去了&#xff0c;管吃管住&#xff0c;这样的朋友真的很难求。 最近离职了&#xff0c;很难想象&#xff0c;一份策划书一天能给你改n次&#xff0c;一周能郁闷&#xff0c;上一个功能没搞完&#xff0c;让你搞下一个功…...

Python爬取豆瓣电影全部分类数据并存入数据库

在当今数字化的时代&#xff0c;网络上丰富的影视资源信息吸引着众多开发者去挖掘和利用。今天&#xff0c;我就来和大家分享一段有趣的代码&#xff0c;它能够从豆瓣电影平台获取相关数据并存储到数据库中哦。 结果展示&#xff08;文末附完整代码&#xff09;&#xff1a; 目…...

算法模板1:排序+二分+高精度+前缀+差分

文章目录 1.1 排序STL sort函数快速排序算法模板归并排序算法模板 1.2 二分整数二分算法模板浮点数二分算法模板 1.3 高精度高精度加法高精度减法高精度乘低精度高精度除以低精度 1.4 前缀和与差分**一维前缀和****二维前缀和****一维差分****二维差分** 之前整理了好多算法模板…...

SpringBoot实现单文件上传

一、在springBoot项目中的pom.xml添加依赖。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency> 二、在资源目录下的static目录下中创建一个upload.html的表单文件…...

rust中解决DPI-1047: Cannot locate a 64-bit Oracle Client library问题

我们在使用rust-oracle crate连接oracle进行测试的过程中&#xff0c;会发现无法连接oracle&#xff0c;测试运行过程中抛出“DPI-1047: Cannot locate a 64-bit Oracle Client library”错误。该问题是由于rust-oracle需要用到oracle的动态连接库&#xff0c;我们通过安装orac…...

YOLOv11(Ultralytics)视频选定区域目标统计计数及跟踪

在计算机视觉的众多应用场景中&#xff0c;对特定区域的目标进行检测、跟踪与计数是一个常见且重要的需求。无论是在智慧交通中统计通过特定路口的车辆数量&#xff0c;还是在零售分析中追踪进入特定区域的顾客行为&#xff0c;这一功能都发挥着不可或缺的作用。 随着深度学习…...

24小时自动监控,自动录制直播蓝光视频!支持抖音等热门直播软件

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 工具特点📒📝 使用🎈 获取方式 🎈⚓️ 相关链接 ⚓️📖 介绍 📖 对于许多直播爱好者和内容创作者而言,错过心爱的直播或难以搜集视频素材始终是一个难题。今天,给大家分享的这款工具可以轻松解决这个问题,它拥有…...

InfiniBand(IB)快速上手

什么是IB&#xff1a; InfiniBand&#xff08;直译为“无限带宽”技术&#xff0c;缩写为IB&#xff09;是一个用于高性能计算的计算机网络通信标准&#xff0c;它具有极高的吞吐量和极低的延迟&#xff0c;用于计算机与计算机之间的数据互连。InfiniBand也用作服务器与存储系…...

D74【 python 接口自动化学习】- python 基础之HTTP

day74 http基础定义 学习日期&#xff1a;20241120 学习目标&#xff1a;http定义及实战 -- http基础介绍 学习笔记&#xff1a; HTTP定义 HTTP 是一个协议&#xff08;服务器传输超文本到浏览器的传送协议&#xff09;&#xff0c;是基于 TCP/IP 通信协议来传递数据&…...

移动光猫[HS8545M5-10]获取超密

移动光猫[HS8545M5-10]获取超级密码 1、缘由2、前期准备2.1、确保本地开通telnet客户端功能2.2、准备好相关软件 3、开始查找超密 1、缘由 最近想折腾一下ipv6ddns打通内外网&#xff0c;查询资料说是需要将光猫桥接到外网&#xff1b;但是使用光猫后边的用户名密码根本就找不到…...

原生JS和CSS,HTML实现开屏弹窗

开屏弹窗常应用于打开游戏&#xff0c;或者打开网站的时候&#xff0c;跳出来在正中间&#xff0c;来显示一些信息&#xff0c;并可以设置今日不再显示 CSS代码如下 <style>#box {width: 100vw;height: 100vh;background-color: rgba(0, 0, 0, 0.2);position: relative…...

vue--制作购物车

&#x1f914;如何制作出下列效果呢&#xff1f;&#x1f447; &#x1f636;‍&#x1f32b;️首先: 设置css样式&#xff1a; <style>body {font-family: Arial, sans-serif;}.cart-item {width: 50%;margin-bottom: 15px;padding: 10px;border: 2px solid gray;borde…...

深度测评腾讯云 HAI 智算服务:高性能 AI 计算的新标杆

本文 一、引言二、产品功能深度解析2.1 多样化的 GPU 配置选择2.2 预配置开发环境示例&#xff1a; 2.3 实时性能监控 三、核心技术特点与优势3.1 云端弹性扩展3.2 高性能计算架构 四、实际测试与代码案例4.1 NLP 案例&#xff1a;使用 BERT 进行情感分类数据集&#xff1a;IMD…...

MQ重复消费与消息顺序

如何避免消息重复消费 RocketMQ&#xff1a;给每个消息分配了一个MessageID。这个MessageID就可以作为消费者判断幂等的依据。这种方式不太建议&#xff0c;原因是在高并发场景下这个MessageID不保证全局唯一性。 最好由业务方创建一个与业务相关的全局唯一的ID来区分消息&am…...

应用商店双弹窗“APP在向用户申请权限时未同步告知用户申请此权限的理由”驳回uni-app应用上线的解决方法

目录 问题分析 解决方法 下载插件包&#xff1a;x-perm-apply-instr 将插件包导入进你项目中的uni_modules文件夹 在项目中的main.js文件中添加以下代码 完成 其它注意事项 addPermisionInterceptor 添加 uniApi 调用拦截 removePermisionInterceptor 移除 uniApi 调用…...

第 32 章 - Go语言 部署与运维

在Go语言的应用开发中&#xff0c;部署与运维是一个非常重要的环节。它不仅关系到应用能否顺利上线&#xff0c;还直接影响到应用的性能、安全性和可维护性。以下是根据您的需求整理的关于Go语言应用的打包和发布、容器化部署、监控和日志管理的相关内容。 1. 应用的打包和发布…...

噪杂环境离线语音通断器效果展示

介于之前的离线语音通断器模块的使用环境大部分为噪音比较小的环境中&#xff0c;部分客户对环境提出了更高的要求&#xff0c;能在噪杂、室外或者有一定的噪音的车内使用的模块开发需求被提高到了一个新的层次。最近找到某些能支持室外噪杂环境使用的芯片和模组&#xff0c;打…...

【django】扩展

1. Promise 1.1 对象和状态 是什么&#xff1f;是前端开发时js中的一个对象&#xff08;包裹&#xff09;。【对象】【异步请求】# 对象中有一个状态的值&#xff0c;status # 创建对象&#xff0c;不赋值&#xff0c;statuspendding let v1 new Promise(function(resolve, …...

逆向破解识别基础

找main函数&#xff1a; &#xff08;使用OllyDbg软件&#xff09; 方法一&#xff1a; 因为main函数需要三个参数&#xff0c;所以遇到三个参数加一个调用&#xff0c;那么可能是main函数。 方法二&#xff1a; 如果main函数中有字符串或者调用函数等一些唯一标识&#x…...

MFC 下拉框显示问题和控件自适应窗口大小

在mfc开发过程中&#xff0c;遇到了下拉框的两个问题&#xff0c;现在记录一下 1、把下拉框点开显示不全我放进去的多条文本 解决办法&#xff1a;把鼠标放到下拉框的倒三角去点一下&#xff0c;鼠标就会变成双向箭头&#xff0c;或者先选中一下下拉框再把鼠标移动到倒三角上去…...

Docker 的存储驱动及其优缺点

Docker 的存储驱动是容器文件系统的关键组成部分&#xff0c;决定了容器镜像和数据的存储方式。以下是常见的存储驱动及其优缺点&#xff1a; 1. OverlayFS/Overlay2 简介: Overlay 是现代 Linux 文件系统中一种高效的联合文件系统&#xff0c;Overlay2 是其改进版本&#xff0…...