【C++基础(八)】类和对象(下)--初始化列表,友元,匿名对象

news2024/11/28 22:43:14

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:C++初阶之路⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学习C++
  🔝🔝


在这里插入图片描述

类和对象

  • 1. 前言
  • 2. 初始化列表
    • 2.1初始化列表的作用
    • 2.2 初始化列表再理解
  • 3. static成员
  • 4. 友元的概念
    • 4.1 友元类
  • 5. 类的匿名对象
  • 6. 总结以及拓展

1. 前言

关于类和对象的大致内容已经结束
本篇文章主要是介绍一些冗杂的细节

虽然本节的内容属于对类和对象锦上添花
但在很多特定的场所下,还是特别使用的!

本章重点:

本篇文章重点讲解初始化列表
友元,匿名对象和类中的static成员
并且介绍类中的内部类的概念

话不多说,进入正题!

在这里插入图片描述


2. 初始化列表

构造函数中,为一个成员赋值
不能叫做对此成员初始化
只能说对此成员赋初始值

由此引出初始化列表:
真正初始化成员变量的地方!

初始化列表:

以冒号开始接着以逗号分隔的成员列表
每个"成员变量"后面跟一个
放在括号中的初始值或表达式

例如:

class Date
{
public:
Date(int year, int month, int day)
   : _year(year)
   , _month(month)
   , _day(day)
 {}
private:
	int _year;
	int _month;
	int _day;
};

初始化列表不止可以像上面一样用
还可以在函数体中再次对变量操作:

Date(int year, int month, int day)
   : _year(year)
   , _month(month)
   , _day(day)
 {
 	 _year++;
	 _day--;
 }

//或者这样

Date(int year, int month, int day)
   : _year(year)
   , _month(month)
 {
 	 _month = month;
 }

2.1初始化列表的作用

有些变量在初始化时必须对它赋值

比如:

  • const成员变量
  • 引用成员变量
  • 没有默认构造的自定义类型成员

然而在构造函数函数体中的赋值
不叫对变量初始化,用上面的类型会报错
所以此时必须用初始化列表

class B
{
public:
	 B(int a, int ref)
	 :_aobj(a)
	 ,_ref(ref)
	 ,_n(10)
	 {}
private:
	 A _aobj;  // 没有默认构造函数的自定义类型
	 int& _ref;  // 引用成员
	 const int _n; // const修饰成员 
};

在之后的学习中,尽量使用初始化列表
进行初始化,因为对于自定义成员来说
不管有没有显示写初始化列表
它都会优先使用初始化列表初始化


2.2 初始化列表再理解

初始化列表中,初始化变量的顺序
是变量在类中声明的顺序
比如以下代码:

class A
{
public:
    A(int a)
       :_a1(a)
       ,_a2(_a1)
   {}
private:
    int _a2;
    int _a1;
};
int main() {
    A aa(1);
}

此时,_a2会先初始化,_a1再初始化

_a2初始化时_a1还是随机值
所以_a2就被初始化成了随机值
而_a1会被初始化为1!

对于C++11缺省值的理解:

成员变量声明时给的缺省值
实际上就是给初始化列表的!

当用户没有显示传参初始化时
编译器会用用户定义的缺省值
当用户显示传参后,缺省值失效
使用用户传的值初始化!

class A
{
public:
    A(int a)//没有显示传参就用缺省值初始化
       :_a1(a)
       ,_a2(a)
   {}
private:
    int _a2 = 1;
    int _a1 = 2;
};
}

3. static成员

概念:

  1. 声明为static的类成员称为类的静态成员

  2. 用static修饰的成员变量
    称之为静态成员变量

  3. 用static修饰的成员函数
    称之为静态成员函数

  4. 静态成员变量一定要在类外进行初始化

static成员的特性:

  • 静态成员为所有类对象共享,放在静态区

  • 静态成员变量必须在类外定义
    类中只是声明

  • 类静态成员即可用
    类名::静态成员对象.静态成员访问

  • 静态成员函数没有隐藏的this指针
    不能访问任何非静态成员

  • 静态成员受访问限定符的限制

使用举例:

class B
{
public:
	 static int Add(int x,int y);//没有this指针,无法访问类中成员
	 static int a;//在类中声明
};
int B::a = 10;//在类外定义

此类的所有成员共同享有这个静态变量


4. 友元的概念

假设一个函数我想定义在类外
但是我又想访问类中的私有成员
只能将私有成员改为共有再访问

这种操作就破坏了类的封装!

引入友元解决此问题:

友元函数可以直接访问类的私有成员
它是定义在类外部的函数,不属于任何类
但需要在类的内部声明
声明时需要加friend关键字

举例说明:

class Date
{
	 friend int Add(int x,int y);//友元函数的声明
public:
	 Date(int year = 1900, int month = 1, int day = 1)
	 : _year(year)
	 , _month(month)
	 , _day(day)
	 {}
private:
	 int _year;
	 int _month;
	 int _day;
};

int Add(int x,int y)//友元函数的定义
{
	x+=_year;
	y+=_month-_day;
	return x+y;
}

在这里插入图片描述

对友元函数的说明:

  • 友元函数可访问类的私有和保护成员
    但不是类的成员函数
  • 友元函数不能用const修饰
  • 友元函数可以在类定义的任何地方声明
    不受类访问限定符限制
  • 一个函数可以是多个类的友元函数
  • 友元函数的调用与普通函数相同

4.1 友元类

除了有友元函数可以访问类私有成员外
声明友元类也可以达到一样的效果
内部类就是友元类的典型代表!

在这里插入图片描述
注:sizeof(外部类)的大小和内部类无关

class A
{
private:
	 static int k;
	 int h;
public:
	 class B // B天生就是A的友元
	 {
	 public:
		 void foo(const A& a)
		 {
			 cout << k << endl;//OK
			 cout << a.h << endl;//OK
		 }
	 };
};

5. 类的匿名对象

先定义一个类:

class Date
{
public:
 Date(int year = 1900, int month = 1, int day = 1)
	 : _year(year)
	 , _month(month)
	 , _day(day)
	 {}
private:
	 int _year;
	 int _month;
	 int _day;
};

使用匿名对象:

Date d = Date(2023,8,1);

这里的:Date(2023,8,1)就是匿名对象

特点:

  • 生命周期只有一行
  • 没有名字,在初始化或销毁时
    自动调用构造或析构函数

匿名对象使用场景:

当定义第一个变量只是为了调用
类中的一个函数,并且调用完后
此变量不会再被使用,此时可用匿名对象

匿名对象极大的简化了代码行!


6. 总结以及拓展

类和对象的所有内容已经讲解完毕
若友遗漏或不对的地方,请在评论指出!

拓展:explicit关键字

构造函数不仅能构造和初始化对象
对于单个参数或除第一个参数无默认值
其余均有默认值的构造函数
还有隐式类型转换的作用

比如:

class Date
{
public:
 Date(int year)
	 : _year(year)
	 {}
private:
	 int _year;
	 int _month = 1;
	 int _day = 1;
};

int main()
{
	Date d = 1999;
	return 0;
}

此处的Date d=1999就是隐式类型转换

然而explicit关键字可以阻止
构造对象时使用隐式类型转换
简直是一个非常卑鄙的关键字[doge]

在这里插入图片描述

使用方法:加在构造函数前

explicit Date(int year)
	 : _year(year)
	 {}

🔎 下期预告:C++内存管理 🔍

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

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

相关文章

nginx基于源码安装的方式对静态页面、虚拟主机(IP、端口、域名)和日志文件进行配置

一.静态页面 1.更改页面内容 2.更改配置文件 3.测试 二.虚拟主机配置 1.基于IP &#xff08;1&#xff09;在html目录下新建目录存放测试文件 &#xff08;2&#xff09;修改nginx.conf文件&#xff0c;在htttp模块中配置两个server模块分别对应两个IP &#xff08;3&am…

Centos7安装openvpn客户端

Background 关于openvpn服务端的部署配置可参考&#xff1a;【Docker安装pritunl】【Centos7使用docke搭建openV】openvpn windows 客户端下载地址 1、下载安装 yum -y install epel-release yum -y install openvpn问题&#xff1a;Error: pritunl-openvpn conflicts with op…

Redis学习笔记Day01-Redis入门

声明&#xff1a;本博客部分内容是从终极SpringBoot讲义摘抄的&#xff0c;文字是OCR识别出来的&#xff0c;有可能存在识别错误的可能&#xff0c;如有错误&#xff0c;请大胆指正&#xff0c;我马上修改&#xff01; 目录 0.官方参考手册API1.连接命令2.key相关命令3.String命…

Android模板设计模式之 - 构建整个应用的BaseActivity

1. 模式介绍 模式的定义 定义一个操作中的算法的框架&#xff0c;而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 模式的使用场景 1.多个子类有公有的方法&#xff0c;并且逻辑基本相同时。 2.重要、复杂的算法&#xff0c;可…

基于Tars高并发IM系统的设计与实现-实战篇6

基于Tars高并发IM系统的设计与实现-实战篇6 客户端设计实现 客户端采用跨平台SDK原生UI的方案。 此处重点介绍SDK实现&#xff0c;UI用户可以根据自己需求进行开发。 方案架构图&#xff1a; 方案实现: TCP链接 CTcpSocket CSSLSocket 长链接维护、数据收发 CTNSendRecvThr…

PHP最简单自定义自己的框架控制器自动加载运行(四)

1、实现效果调用控制中方法 2、创建控制器indexCrl.php <?php class indexCrl{public function index(){echo 当前index控制器index方法;} } 3、KJ.php字段加载控制器文件 public static function run(){//定义常量self::_set_const();//创建模块目录self::_mk_module();…

Windows下运行Tomcat服务时报GC Overhead Limit Exceeded

根本原因是在新建Tomcat作为Windows服务时&#xff0c;系统默认设置的堆内存太小了&#xff0c;我们打开/bin/service.bat文件&#xff0c;将如下图所示的默认值改大一些就好了 if "%JvmMs%" "" set JvmMs512 if "%JvmMx%" "" set J…

嵌入式AI芯片架构用处

Blaize将其GSP描述为能够执行“直接图处理&#xff0c;片上任务图管理和执行以及任务并行性”。简而言之&#xff0c;Blaize设计了GSP来满足AI&#xff0c;GPU&#xff0c;CPU或DSP以前无法满足的处理需求。 对于许多涉及嵌入式ai处理器的行业分析师而言&#xff0c;这是他们之…

算法通关村——轻松搞定最大深度问题

前言 二叉树的深度&#xff1a;从根节点到当前节点的最长简单路径边的条数 题目 给定一个二叉树&#xff0c;找出其最大深度&#xff0c;二叉树的深度为根节点到最远叶子节点的最长路径上的节点数 说明 如下图所示&#xff0c;对于node(3) &#xff0c; 最大深度自然是左右子节…

pmp考试是智商税吗,是一场持久的割韭菜战吗?

在一些大型企业中&#xff0c;PMP认证已成为担任“项目经理”必备的资格之一。此外&#xff0c;在国际上&#xff0c;PMP认证也成为参与项目招标的必要条件之一&#xff0c;只有拥有PMP认证的项目经理所在的公司才有资格参与竞标&#xff0c;而承建项目经理也必须持有PMP认证。…

RabbitMQ 安装教程

RabbitMQ 安装教程 特殊说明 因为RabbitMQ基于Erlang开发&#xff0c;所以安装时需要先安装Erlang RabbitMQ和Erlang版本对应关系 查看地址&#xff1a;www.rabbitmq.com/which-erlan… 环境选择 Erlang: 23.3及以上 RabbitMQ: 3.10.1Windows 安装 1. 安装Erlang 下载地…

海外进出口跨境电商独立站开发(多语言+多货币)

要搭建一个海外进出口跨境电商独立站开发&#xff0c;需要考虑以下几个方面&#xff08;以下步骤不分先后&#xff09;&#xff1a; 设计系统架构在开始编写代码之前&#xff0c;首先需要设计系统的整体架构。对于一个大型的电商系统&#xff0c;需要考虑系统可扩展性、高可用…

NameError: No such file or directory 解决方法

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 问题 最近有小伙伴经常问到这个报错&#xff0c;今天来分享一下具体怎么解决。 [Errno 2] No such file or directory: ./mnist_image_label/mnist_train_jpg_60000.txt这个没有查找到子文件或者子文件夹的问题 解决…

CPU与硬件的交互方式(中断、轮询)

CPU与硬件的交互方式 轮询方式&#xff1a;CPU不断的访问硬件有没有进行操作&#xff0c;如果接收到了信息&#xff0c;CPU就处理。如果没有过一会在访问一遍 直到有信息为止 中断方式&#xff1a;硬件操作的时候会写一个中断&#xff0c;向CPU发送这个中断&#xff0c;CPU正常…

【LeetCode】练习习题集【4月 - 7 月】

LEETCODE习题集【4月-7月总结】 简单 数组部分 1.重复数 题目&#xff1a; 在一个长度u为 n 的数组 nums 里的所有数字都在 0&#xff5e;n-1 的范围内。数组中某些数字是重复的&#xff0c;但不知道有几个数字重复了&#xff0c;也不知道每个数字重复了几次。请找出数组中…

网络安全—黑客技术【自学】

一、黑客是什么 原是指热心于计算机技术&#xff0c;水平高超的电脑专家&#xff0c;尤其是程序设计人员。但后来&#xff0c;黑客一词已被用于泛指那些专门利用电脑网络搞破坏或者恶作剧的家伙。 二、学习黑客技术的原因 其实&#xff0c;网络信息空间安全已经成为海陆空之…

Linux驱动——input子系统

一、input子系统基本框架 Linux内核为了两个目的&#xff1a; 简化纯输入类外设&#xff08;如&#xff1a;键盘、鼠标、游戏杆、轨迹球、触摸屏。。。等等&#xff09;的驱动开发 统一输入类外设产生的数据格式&#xff08;struct input_event&#xff09;&#xff0c;更加方…

将你的计算机变身为果园守护者:与本地树莓派建立连结的乐趣探索!!

如何连接本地树莓派 文章目录 如何连接本地树莓派前言1. 操作流程2. 打开树莓派SSH功能3. 确认树莓派信息后 安装相应SSH客户端 &#x1f341; 小结 &#x1f341; 前言 树莓派作为一款以教育为目的推出的硬件系统&#xff0c;也是超低功耗的微型“准系统”&#xff0c;能够提…

Redis的RDB持久化

Redis是一个键值对数据库服务器&#xff0c;服务器中通常包含着任意个非空数据库&#xff0c;而每个非空数据库中又可以包含任意个键值对&#xff0c;为了方便起见&#xff0c;我们将服务器中的非空数据库以及它们的键值对统称为数据库状态。 举个例子&#xff0c;下图展示了一…

模仿学习(行为克隆,逆强化学习,生成式对抗模仿学习)

目录 1.模仿学习 1.1先说强化学习 1.2再说逆强化学习 1.3最后说生成对抗模仿学习 1.3.1先说GAN 1.3.2再说生成对抗模仿学习 1.4逆强化学习常用方法 参考文献 1.模仿学习 定义&#xff1a;当我们想训练机器人时&#xff0c;通过复制人类的动作&#xff0c;对机器人进行训…