当前位置: 首页 > 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…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...