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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/477696.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据指标与标签在数据分析中的关系与应用

导读&#xff1a;分享数据指标体系的文章很多&#xff0c;但讲数据标签的文章很少。实际上&#xff0c;标签和指标一样&#xff0c;是数据分析的左膀右臂&#xff0c;两者同样重要。实际上&#xff0c;很多人分析不深入&#xff0c;就是因为缺少对标签的应用。今天系统的讲解下…

Exploring Prompt Engineering: A Systematic Review with SWOT Analysis

文章目录 题目摘要简介方法论背景相关工作评估结论 题目 探索快速工程&#xff1a;基于 SWOT 分析的系统评价 论文地址&#xff1a; https://arxiv.org/abs/2410.12843 摘要 在本文中&#xff0c;我们对大型语言模型 (LLM) 领域的提示工程技术进行了全面的 SWOT 分析。我们强…

Android 常用命令和工具解析之内存相关

目录 1 基本概念 1.1 PSS & RSS & USS & VSS 1.1.1 PSS 1.1.2 RSS 1.2 Dirty & Clean & SwapPss 1.2.1 Private Dirty 1.2.2 Private Clean 1.2.3 SwapPss Dirty 1.3 Swap & buffers & cache 1.3.1 Swap 1.3.2 buffers 1.3.3 cache 2…

使用Go 语言连接并操作 MySQL 数据库

新建项目&#xff0c;我这里使用的vscode&#xff1a; 1.新建项目初始化&#xff1a; 手动创建工程文件夹go安装目录->src->projectName 在项目下创建 main.go文件&#xff1a; 在vscode中点击文件->打开文件夹&#xff0c;选择刚刚新建的文件夹。打开后&#xff0…

YOLOv11融合[NeurlS2022]递归门控卷积gnconv模块及相关改进思路

YOLOv11v10v8使用教程&#xff1a; YOLOv11入门到入土使用教程 YOLOv11改进汇总贴&#xff1a;YOLOv11及自研模型更新汇总 《HorNet: Efficient High-Order Spatial Interactions with Recursive Gated Convolutions》 一、 模块介绍 论文链接&#xff1a;https://arxiv.org…

从零开始-VitePress 构建个人博客上传GitHub自动构建访问

从零开始-VitePress 构建个人博客上传GitHub自动构建访问 序言 VitePress 官网&#xff1a;VitePress 中文版 1. 什么是 VitePress VitePress 是一个静态站点生成器 (SSG)&#xff0c;专为构建快速、以内容为中心的站点而设计。简而言之&#xff0c;VitePress 获取用 Markdown…

使用Notepad++工具去除重复行

使用Notepad工具去除重复行 参考链接&#xff1a;https://blog.csdn.net/londa/article/details/108981396 一 、使用正则表达式 1、对文本进行排序&#xff0c;让重复行排在一起 2、使用正则表达式替换&#xff08;注意&#xff09;^(.*?)$\s?^(?.*^\1$) 在替换时选择正…

RabbitMQ和RocketMQ相关面试题

RabbitMQ和RocketMQ面试题 RabbitMQ1.RabbitMQ各部分角色2.如何确保RabbitMQ消息的可靠性&#xff1f;3.什么样的消息会成为死信&#xff1f;4.死信交换机的使用场景是什么&#xff1f;5.TTL6.延迟队列7.消息堆积问题8.MQ集群 RocketMQ1.RocketMQ各部分角色2.RocketMQ如何保证高…

【机器学习chp5】线性回归

推荐文章1&#xff0c;三种角度详细分析了L1&#xff0c;L2正则化的本质。 【王木头 L1、L2正则化】三个角度理解L1、L2正则化的本质-CSDN博客 推荐文章2&#xff0c;其中有各种梯度下降的优化算法分析。 【王木头梯度下降法优化】随机梯度下降、牛顿法、动量法、Nesterov、…

【AI系统】GPU 架构回顾(从2018年-2024年)

Turing 架构 2018 年 Turing 图灵架构发布&#xff0c;采用 TSMC 12 nm 工艺&#xff0c;总共 18.6 亿个晶体管。在 PC 游戏、专业图形应用程序和深度学习推理方面&#xff0c;效率和性能都取得了重大进步。相比上一代 Volta 架构主要更新了 Tensor Core&#xff08;专门为执行…

Windows11深度学习环境配置

CUDA、CUDNN 一、安装另一个版本的CUDA 下载.exe文件&#xff0c;网址打不开自己开热点就能解决&#xff1a;CUDA Toolkit 11.2 Downloads | NVIDIA Developer 若遇到“You already have a newer version of the NVIDIA Frameview SDK installed” 1.把电脑已经存在的FrameVi…

H.265流媒体播放器EasyPlayer.js H5流媒体播放器关于如何查看手机端的日志信息并保存下来

现今流媒体播放器的发展趋势将更加多元化和个性化。人工智能的应用将深入内容创作、用户体验优化等多个方面&#xff0c;带来前所未有的个性化体验。 EasyPlayer.js H.265流媒体播放器属于一款高效、精炼、稳定且免费的流媒体播放器&#xff0c;可支持多种流媒体协议播放&#…

力扣.5.最长回文子串力扣.14最长公共前缀力扣219.存在重复元素II力扣.67二进制求和

目录 力扣.5.最长回文子串 力扣.14最长公共前缀 力扣219.存在重复元素II 力扣.67二进制求和 力扣.5.最长回文子串 中心拓展算法&#xff0c;假设以i位置为中心两边可以扩展到多少&#xff0c;所以当对应一个中间位置的时候&#xff0c;可以定义两个指针&#xff0c;对应一个…

Vue.js 插槽 Slots 实际应用 最近重构项目的时候遇到的...

前端开发中 插槽 Slots 是一个重要的概念 我们可以查看一下vue.js的官方文档 https://cn.vuejs.org/guide/components/slots 类似于连接通道一样 可以把核心代码逻辑搬到另外的地方 做一个引用 而原先的地方可能并不能这样书写 对于这个概念我在vue的官方文档里面找到了…

快速识别模型:simple_ocr,部署教程

快速识别图片中的英文、标点符号、数学符号、Emoji, 模型会输出图片中文字行的坐标位置、最低得分、识别结果。当前服务用到的模型&#xff1a;检测模型、数字识别、英文符号识别。 一、部署流程 1.更新基础环境 apt update2.安装miniconda wget https://repo.anaconda.com/…

Android mk/bp构建工具介绍

零. 前言 由于Bluedroid的介绍文档有限&#xff0c;以及对Android的一些基本的知识需要了(Android 四大组件/AIDL/Framework/Binder机制/JNI/HIDL等)&#xff0c;加上需要掌握的语言包括Java/C/C等&#xff0c;加上网络上其实没有一个完整的介绍Bluedroid系列的文档&#xff0…

docker安装使用Elasticsearch,解决启动后无法访问9200问题

1.docker安装、启动es docker pull elasticsearch:8.13.0docker images启动容器 docker run -d -p 9200:9200 -p 9300:9300 -e ES_JAVA_OPTS"-Xms256m -Xmx256m" --name es01 8ebd258614f1-d 后台运行-p 9200:9200 -p 9300:9300 开放与主机映射端口-e ES_JAVA_OPTS…

揭秘云计算 | 5、关于云计算效率的讨论

一、 公有云效率更高&#xff1f; 解&#xff1a;公有云具有更高的效率。首先我们需要知道效率到底指的是什么。这是个亟须澄清的概念。在这里效率是指云数据中心&#xff08;我们将在后文中介绍其定义&#xff09;中的IT设备资源利用率&#xff0c;其中最具有代表性的指标就是…

【终端美化】Ubuntu 下 Zsh 与 Oh-My-Zsh 美化与插件配置指南

目录 1. 检查是否已安装 zsh2. 安装 zsh3. 设置 zsh 为默认 Shell4. 安装 oh-my-zsh4.1 使用 curl 安装4.2 使用 wget 安装&#xff08;如果 curl 不可用&#xff09;4.3 迁移 Bash 自定义配置到 Zsh打开Files并显示隐藏文件复制需要的配置内容粘贴到 Zsh 配置文件保存并关闭文…

Spring Boot与MyBatis-Plus的高效集成

Spring Boot与MyBatis-Plus的高效集成 引言 在现代 Java 开发中&#xff0c;MyBatis-Plus 作为 MyBatis 的增强工具&#xff0c;以其简化 CRUD 操作和无需编写 XML 映射文件的特点&#xff0c;受到了开发者的青睐。本篇文章将带你一步步整合 Spring Boot 与 MyBatis-Plus&…