C++(类和对象---下)

news2024/10/6 8:28:37

目录

  • 初始化列表
  • 构造函数?拷贝构造?
  • 浅谈explicit关键字
    • 友元
  • 内部类
  • static成员
  • 总结

在这里插入图片描述

初始化列表

引入初始化列表:简化代码,提高效率

在编程中,初始化列表是一种用于在创建对象时初始化成员变量的快捷方式。通过初始化列表,可以在对象构造时直接为成员变量赋值,而无需在构造函数体内进行赋值操作。这不仅使代码更简洁清晰,还可以提高程序的执行效率。

在本文中,我们将深入探讨初始化列表的概念及其在不同编程语言中的应用。我们将介绍初始化列表的语法结构,并通过具体的示例代码演示如何在常见的编程语言中使用初始化列表。无论您是初学者还是有一定经验的开发者,本文都将为您带来有价值的信息。

初始化列表的格式

class AA
{
public:
	AA(int n)
		:_a(n)
		,_b(n)
	{}
private:
	int _a;
	int _b;
};

d队列的初始化列表

	MyQueue(int n,int &rr)
		:_pushst(n)//调用构造函数
		, _popst(n)
		,_size(0)
		{}

注意
1、对于上面的初始化列表,_pushst_popst是自定义类型,所以后面加个括号其实就是调用它的构造函数,我们可以这样理解

2、如果我们要初始化const修饰的变量时,只能在初始化列表中初始化,因为const修饰的变量具有常性,所以只能在初始化列表中初始化

3、当我们要初始化一个成员变量是引用时,也必须在初始化列表中初始化

注意:初始化列表是成员变量定义的地方,而类中的成员变量只是成员变量的声明

如果我们不写初始化列表会生成初始化列表吗?

答案是肯定的,我们可以在成员变量声明的时候给一些缺省参数,我们可以定义一个类,然后用调试器进行调试,在调试中我们可以发现,我们进入这个类的时候会直接跳到缺省参数的那几行,我们可以打开监视器进行观察,也可以看见,类中的成员就是用缺省值进行初始化的
在这里插入图片描述

构造函数?拷贝构造?

int main()
{
	AA a1(1);//构造函数
	AA a2 = a1;//拷贝构造
	AA a3 = 1;//?
	return 0;
}

第一个是构造函数第二个是拷贝构造,那第三个是什么呢?

第三个是隐式类型转换
在C语言中下面代码会生成一个临时变量

double b=3.3;
int a=b;

对于上面代码会生成一个临时变量,b先生成一个临时变量tmp,tmp是int类型,然后tmp再赋值给a

在这里插入图片描述
所以回归正传,刚刚我们用一个类等于一个数字,其实是一个隐式类型转换,本质是1先调用构造函数创建一个tmp的对象,然后再利用tmp再拷贝拷贝构造给a3

如果用AA&a3会报错,因为1具有常性,a3是tmp的引用a3可以修改,但是因为常性不能修改,所以会报错,这里就是权限的放大,所以我们可以在前面加一个const

	const AA& a3 = 1;

通过下面题目来引入一个初始化列表的规则

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();
}
	A. 输出1  1
	B.程序崩溃
	C.编译不通过
	D.输出1  随机值

对于上面这道题肯定不会选择A,因为往往这种题,都不可能这么直接,更不可能选择B,因为B是程序崩溃,往往程序崩溃只会出现在野指针和空指针中,只有从c和D中选,肯定可以排除C因为不可能编译错误。

从上面的题目中我们就可以得到一个规则,初始化列表的初始化顺序与初始化列表的顺序无关,只与声明时的顺序有关

上面我们讨论的是只有一个参数的时候的初始化,当有两个参数时我们应该如何传参呢

两个参数的参数列表的传参和数组类似

class AA
{
public:
	AA(int n = 1, int m = 2)
		:_a(n)
		, _b(n)
	{}
private:
	int _a = 1;
	int _b = 0;
};
int main()
{
	AA a1(1);
	AA a2 = a1;
	const AA& a3 = 1;
	AA aa4 = { 1,2 };
	return 0;
}

当有两个参数的时候,就可以利用C99的语法进行初始化,其实等号也可以省略,最好把等号加上

浅谈explicit关键字

前面我们谈了隐式类型转换,如果我们不想进行隐式类型转换可以在函数前面加一个explicit关键字

智能指针是explicit关键字的使用场景

友元

友元函数就是全局函数,只不过是写在了类中,友元函数可以直接访问类中的私有成员变量,下面我们简单的写一个友元函数作为示范:
在声明中可以像下面这样声明:

	friend ostream& operator<<(ostream& out, const Date& d);
	friend istream& operator>>(istream& in, Date& d);

一般情况下,我们都会把友元函数的声明声明在类中的最前面,声明完了之后,友元函数在定义中还是像正常函数一样写,前面不用加friend

友元的特性

  1. 友元关系是单向的,不具有交换性。
    比如上述Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接
    访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。
  2. 友元关系不能传递
    如果C是B的友元, B是A的友元,则不能说明C时A的友元。
  3. 友元关系不能继承,在继承位置再给大家详细介绍。

出了友元函数还有友元类,在友元类中我们可以用另一个类中的私有成员变量

下面是友元类的声明

class Time
{
   friend class Date;   // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类
中的私有成员变量
public:
 Time(int hour = 0, int minute = 0, int second = 0)
 : _hour(hour)
 , _minute(minute)
 , _second(second)
 {}
  
private:
   int _hour;
   int _minute;
   int _second;
};
class Date
{
public:
   Date(int year = 1900, int month = 1, int day = 1)
       : _year(year)
       , _month(month)
       , _day(day)
   {}
  
   void SetTimeOfDate(int hour, int minute, int second)
   {
       // 直接访问时间类私有的成员变量
       _t._hour = hour;
       _t._minute = minute;
       _t._second = second;
   }
  
private:
   int _year;
   int _month;
   int _day;
   Time _t;
};

内部类

内部类就是、一个类中定义另一个类
内部类的特性:内部类是外部类的天生的友元类,内部类可以随意访问外部类的成员变量

注意:内部类也是一个单独的类,唯一的区别是受到了外部类域的限制,所以计算外部类的大小的时候,不需要加上内部类的大小,只需要算外部类的成员变量的大小即可

如果内部类定义在Public中则外面也可以访问,如果内部类定义在private中则只有类的内部才能访问

static成员

我们来计算一下下面的类的大小:

class BB
{
public:

private:
	int _b1;
	static int _b1;
};

注意成员变量不存函数和静态变量,一个存放在代码区,一个存放在静态区,所以在计算类的大小的时候,我们也不计算static修饰的成员变量

在C语言中我们知道,static修饰的变量只初始化一次,且在定义的时候初始化,因为在类中的是声明所以我们不应该给成员变量缺省值,也不应该将static修饰的成员变量放在初始化列表中进行初始化

正确的初始化方法如下:

class BB
{
public:

private:
	int _b1;
	static int _b1;
};
int BB::_b1 = 1;
int main()

特性

  1. 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区
  2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明
  3. 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问
  4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
  5. 静态成员也是类的成员,受public、protected、private 访问限定符的限制

总结

通过本文的介绍,我们深入探讨了几个编程中的关键概念:友元、初始化列表、静态成员变量以及内部类。友元使得类之间的访问更加灵活,但也需要慎重使用以保持封装性;初始化列表能够简化对象的构造过程,提高代码效率;静态成员变量共享于类的所有对象,是实现全局数据共享和类特性存储的有效方式;内部类则可以在一个类的内部定义另一个类,便于组织和封装相关的功能。

深入理解这些概念对于成为一名优秀的程序员至关重要。熟练掌握它们不仅可以提高代码的质量和效率,还能够拓展我们的编程思维,使我们更加灵活地应对不同的问题和挑战。

在实际编程中,我们应该根据具体情况合理运用这些概念,从而编写出清晰、高效且易于维护的代码。希望本文能够为您在编程学习和实践中提供一些帮助和启发。让我们继续不断学习和探索,成为更加优秀的程序员!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python爬虫原理和编程实战:爬取CSDN博主的账号信息

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟,欢迎关注。提供嵌入式方向的学习指导…

时间同步服务项目练习

一.配置server主机要求如下&#xff1a; 1.server主机的主机名称为 ntp_server.example.com 2.server主机的IP为&#xff1a; 172.25.254.100 3.server主机的时间为1984-11-11 11&#xff1a;11&#xff1a;11 4.配置server主机的时间同步服务要求可以被所有人使用 二.设定cli…

RocketMQ 10 面试题FAQ

RocketMQ 面试FAQ 说说你们公司线上生产环境用的是什么消息中间件? 为什么要使用MQ&#xff1f; 因为项目比较大&#xff0c;做了分布式系统&#xff0c;所有远程服务调用请求都是同步执行经常出问题&#xff0c;所以引入了mq 解耦 系统耦合度降低&#xff0c;没有强依赖…

Java | Leetcode Java题解之第31题下一个排列

题目&#xff1a; 题解&#xff1a; class Solution {public void nextPermutation(int[] nums) {int i nums.length - 2;while (i > 0 && nums[i] > nums[i 1]) {i--;}if (i > 0) {int j nums.length - 1;while (j > 0 && nums[i] > nums[…

构建数据平台架构指导原则与平台核心组件说明

文章目录 前言什么是数据架构&#xff1f;数据架构如何帮助构建数据平台&#xff1f;数据平台核心组件数据源系统数据加载数据存储数据处理和转换提供使用数据的方式公共服务 前言 湖仓一体是最近几年非常流行的现代大数据架构&#xff0c;目前它已经成为设计数据平台架构的首…

JavaSE-13笔记【集合2(+2024新)】

文章目录 3.Map3.1 Map继承结构3.2 Map接口的常用方法3.3 遍历Map3.4 HashMap集合3.4.1 HashMap集合key的特点3.4.2 HashMap集合的key存储自定义类型3.4.3 哈希表3.4.3.1 哈希表的介绍3.4.3.2 哈希表的存储原理 3.4.4 存放在HashMap和HashSet集合key部分的元素必须同时重写hash…

postman汉化

一、postman历史版本下载&#xff1a;Postman 10.24.16 Download for Windows / Old Versions / FileHorse.comhttps://www.filehorse.com/download-postman/old-versions/ 二、汉化包下载&#xff1a; Releases hlmd/Postman-cn GitHubPostman汉化中文版. Contribute to h…

LeetCode———144—— 二叉树的前序遍历

目录 ​编辑 1.题目 2.解答 1.首先计算二叉树的节点个数&#xff1a; 2.以先序遍历&#xff08;Preorder Traversal&#xff09;的方式遍历一个二叉树&#xff0c;并将遍历到的节点的值存储在一个整数数组中 3.最终代码 1.题目 . - 力扣&#xff08;LeetCode&#xff09; 给…

浮点数的存储方式、bf16和fp16的区别

目录 1. 小数的二进制转换2. 浮点数的二进制转换3. 浮点数的存储3.1 以fp32为例3.2 规约形式与非规约形式 4. 各种类型的浮点数5. BF16和FP16的区别Ref 1. 小数的二进制转换 十进制小数转换成二进制小数采用「乘2取整&#xff0c;顺序排列」法。具体做法是&#xff1a;用 2 2…

如何协调数据集成和数据质量?

想象一下用腐烂的木头制作的一件漂亮的家具或用劣质面料制成的高级时尚衬衫。材料的质量影响最终产品。那么&#xff0c;为什么数据洞察&#xff08;贵公司庞大的数据管理工作的主要产品&#xff09;会有所不同呢&#xff1f; 无论您的数据管理生态系统有多强大&#xff0c;或…

《自动机理论、语言和计算导论》阅读笔记:p139-p171

《自动机理论、语言和计算导论》学习第 7 天&#xff0c;p139-p171总结&#xff0c;总计 33 页。 一、技术总结 1.reversal p139, The reversal of a string a1a2…an is the string written backwards, that is anan-1…a1. 2.homomorphism A string homomorphism is a f…

点云语义分割:使用Cylinder3D训练SemanticKITTI数据集

点云语义分割:使用Cylinder3D训练SemanticKITTI数据集 一、环境二、数据准备3、训练4、测试5、可视化 一、环境 系统&#xff1a;Ubuntu18 Pytorch&#xff1a;1.5.0 GPU&#xff1a;Tesla V100 cuda&#xff1a;10.2 代码: Cylinder3D 二、数据准备 下载semanticKITTI数据集…

32.5k star!发现一个新的 API 调试工具!postman 要被替换了【文末有项目源码】

在软件开发过程中&#xff0c;API&#xff08;应用程序接口&#xff09;扮演着至关重要的角色。为了确保 API 的可靠性和性能&#xff0c;开发人员需要一种高效的方式来测试和调试它们。这方面的工具&#xff0c;大家经常用到的应该就是 postman 了。不过&#xff0c;今天想要给…

钡铼IOy系列模块深挖工业场景需求提供丰富多样的I/O解决方案

钡铼IOy系列模块以其灵活性和多样性&#xff0c;在工业场景中提供了丰富多样的I/O解决方案&#xff0c;满足了不同行业、不同应用场景的需求。以下是一些常见的工业场景需求及钡铼IOy系列模块提供的解决方案&#xff1a; 1. 工厂自动化 需求&#xff1a;工厂自动化需要对生产线…

03-JAVA设计模式-迭代器模式

迭代器模式 什么是迭代器模式 迭代器模式&#xff08;demo1.Iterator Pattern&#xff09;是Java中一种常用的设计模式&#xff0c;它提供了一种顺序访问一个聚合对象中各个元素&#xff0c;而又不需要暴露该对象的内部表示的方法。迭代器模式将遍历逻辑从聚合对象中分离出来…

斯坦福大学2024年人工智能发展和前景全面分析报告

2024 年指数是斯坦福大学迄今为止最全面的指数&#xff0c;恰逢人工智能对社会的影响力达到前所未有的重要时刻。今年&#xff0c;斯坦福大学扩大了研究范围&#xff0c;更广泛地涵盖人工智能的技术进步、公众对该技术的看法以及围绕其发展的地缘政治动态等基本趋势。 完整详细…

C++基本输入输出

C 中的输入和输出&#xff08; I/O &#xff09;主要是通过标准库中的输入输出流来实现的。最常用的是 iostream 1. 库&#xff0c;它提供了用于输入和输出的基本流类&#xff0c;包括 cin 、 cout 、 cerr 和 clog 。 1.标准输出流 ( cout ) cout 代表标准输出流&a…

Java 基于微信小程序的医院预约挂号小程序(V3)

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

短信防刷之滑动验证码

前言&#xff1a;最近想写一个滑动验证码&#xff0c;前台的样式虽然很好看&#xff0c;但是并不安全&#xff0c;网上也都是一些demo&#xff0c;不是前后台分离的&#xff0c;然后就自己查资料&#xff0c;自己来完成了 滑动验证码 一、为什么要使用滑动验证码 首先&#x…

C++ 秋招必知必会(数据结构与算法:下)

20. 二叉树的定义与操作 二叉树&#xff08;binary tree&#xff09;是一种非线性数据结构&#xff0c;代表着祖先与后代之间的派生关系&#xff0c;体现着“一分为二”的分治逻辑 与链表类似&#xff0c;二叉树的基本单元是节点&#xff0c;每个节点包含&#xff1a;值、左子…