详解C++类和对象(下)完结篇

news2024/9/26 20:11:20

文章目录

  • 写在前面
  • 1. 进一步认识构造函数
    • 1.1 初始化列表
    • 1.2 初始化列表的特性
    • 1.3 explicit关键字
  • 2. static成员变量和static成员函数
    • 2.1 static成员的概念
    • 2.2 static成员的特性
  • 3. 友元
    • 3.1 友元函数
    • 3.1 友元类
  • 4. 内部类
  • 5.匿名对象

写在前面

本篇文章详细介绍了C++类和对象中几个重要的概念和特性,包括初始化列表、Static成员、内部类等,下面我们来一一介绍它们。

1. 进一步认识构造函数

通过上篇文章的介绍,我们知道在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。

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;
};

虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化,构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值
在这里插入图片描述
因此,为了给成员变量一个定义初始化的地方,C++规定了成员变量在初始化列表中进行初始化。

1.1 初始化列表

初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式
在这里插入图片描述

1.2 初始化列表的特性

  1. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)。
    在这里插入图片描述

  2. 类中包含以下成员,必须放在初始化列表位置进行初始化。
    引用成员变量
    const成员变量
    自定义类型成员(且该类没有默认构造函数时)
    在这里插入图片描述

  3. 尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,
    一定会先使用初始化列表初始化。
    在这里插入图片描述
    上篇文章中提到的在成员变量声明的时候给初始值,如果我们没有使用初始化列表,这个初始值就会在初始化列表的地方使用。
    在这里插入图片描述

  4. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关。
    我们来思考一下下面代码的运行结果是什么?

#include <iostream>
using namespace std;

class A
{
public:
	A(int a = 1)
		:_a1(a), _a2(_a1)
	{
	}

	void Print()
	{
		cout << " _a1 = " << _a1 << ' ' << " _a2 = " << _a2 << endl;
	}
private:
	int _a2;
	int _a1;
};

int main()
{
	A a;
	a.Print();
	return 0;
}

运行结果:
在这里插入图片描述
我们不禁会发出疑问,为啥_a2的值是随机值呢?
下面我们来分析一下:
在这里插入图片描述

1.3 explicit关键字

构造函数不仅可以构造与初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值
的构造函数,还具有类型转换的作用

例如下面这种情况:
在这里插入图片描述
如果不想发生上述的类型转换,可以使用explicit修饰构造函数,将会禁止构造函数的隐式转换

#include <iostream>
using namespace std;

class Date
{
public:
	/*explicit Date(int year = 1900)
		:_year(year)
	{
	}*/
	explicit Date(int year, int month = 1, int day = 1)
		:_year(year),_month(month),_day(day)
	{
	}

	Date& operator=(const Date& d)
	{
		//检查是否是自己给自己赋值
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
	}
private:
	int _year;
	int _month;
	int _day;
};


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

在这里插入图片描述

2. static成员变量和static成员函数

2.1 static成员的概念

在C++中,static 关键字可以用于声明类的成员变量和成员函数,使它们成为类的静态成员。静态成员属于类本身,而不是类的对象,因此所有属于该类的对象共享同一个静态成员。

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化**。

2.2 static成员的特性

  1. 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区。
    在这里插入图片描述

  2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明。
    在这里插入图片描述

  3. 类静态成员即可用类名::静态成员或者对象.静态成员来访问。
    在这里插入图片描述

  4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员。
    在这里插入图片描述

  5. 静态成员也是类的成员,受public、protected、private 访问限定符的限制。
    在这里插入图片描述

通过上面的介绍,我们来思考下面两个问题:
静态成员函数可以调用非静态成员函数吗?
非静态成员函数可以调用类的静态成员函数吗?
在这里插入图片描述

3. 友元

在 C++ 中,友元是一种机制,允许某些非成员函数或外部类访问一个类的私有成员。通过友元关系,外部函数或类可以直接访问另一个类的私有成员,而无需通过公有接口。友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。
友元分为:友元函数友元类

3.1 友元函数

之前我们想打印Date类的成员,是需要自己实现一个Print函数。那能不能使得Date类像内置类型一样,使用cout实现呢?
答案是可以的,这里重载一下流插入(<<)操作符就可以实现。
在这里插入图片描述
下面我们来重载一下Date类的流插入(<<)操作符。

#include <iostream>
using namespace std;

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
		:_year(year), _month(month), _day(day)
	{}
	//重载一下流插入<<操作符
	ostream& operator<<(ostream& out)
	{
		out << _year << '/' << _month << '/' << '_day' << endl;
		return out;
	}

private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1(2024, 2, 7);
	Date d2(2024, 2, 8);

	cout << d1 << d2 << endl;

	return 0;
}

现在有个问题:现在尝试去重载operator<<,然后发现没办法将operator<<重载成成员函数。运行上面代码报错。
在这里插入图片描述

因为cout的输出流对象和隐含的this指针在抢占第一个参数的位置。this指针默认是第一个参数也就是左操作数了。但是实际使用中cout需要是第一个形参对象,才能正常使用。所以要将operator<<重载成全局函数。但又会导致类外没办法访问成员。
在这里插入图片描述

此时就需要友元来解决。operator>>同理。友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字
在这里插入图片描述
友元函数特性:

  1. 友元函数可访问类的私有和保护成员,但不是类的成员函数。
  2. 友元函数不能用const修饰。因为友元函数不是类的成员函数,且没有隐藏的this指针,而const是修饰类的成员函数,修饰的是this指针。
  3. 友元函数可以在类定义的任何地方声明,不受类访问限定符限制。
  4. 一个函数可以是多个类的友元函数。
  5. 友元函数的调用与普通函数的调用原理相同。

3.1 友元类

友元类是指在类中通过 friend 关键字声明的外部类,外部类可以访问该类的私有成员和受保护成员
在这里插入图片描述
现在将友元声明注释掉,编译器就会报错。
在这里插入图片描述

友元类特性:

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

4. 内部类

如果在一个类定义在另一个类的内部这个内部类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员外部类对内部类没有任何优越的访问权限
注意:内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元
在这里插入图片描述
内部类特性:

  1. 内部类可以定义在外部类的public、protected、private都是可以的,但是受类域和访问限定符的限制。
    在这里插入图片描述

  2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。

  3. sizeof(外部类)=外部类,和内部类没有任何关系。
    在这里插入图片描述

5.匿名对象

匿名对象的概念:
匿名对象是指在不使用变量名的情况下创建的临时对象,它在创建后立即被使用,通常用于简化代码或执行一次性操作。匿名对象可以在需要对象的地方直接创建并使用,而无需定义变量名。

那么我们该如何定义一个匿名对象呢?
在这里插入图片描述
匿名对象的特性:

  1. 定义匿名对象的时候不用给对象取名字。
  2. 生命周期只在定义的一行,程序执行到下一行他就会自动调用析构函数。
    在这里插入图片描述

匿名对象使用场景:
匿名对象在这样场景下就很好用,当然还有一些其他使用场景,这个我们以后遇到了再说。
在这里插入图片描述

至此,本片文章就结束了,若本篇内容对您有所帮助,请三连点赞,关注,收藏支持下。

创作不易,白嫖不好,各位的支持和认可,就是我创作的最大动力,我们下篇文章见!

如果本篇博客有任何错误,请批评指教,不胜感激 !!!
在这里插入图片描述

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

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

相关文章

基于SpringBoot+Vue的校园博客管理系统

末尾获取源码作者介绍&#xff1a;大家好&#xff0c;我是墨韵&#xff0c;本人4年开发经验&#xff0c;专注定制项目开发 更多项目&#xff1a;CSDN主页YAML墨韵 学如逆水行舟&#xff0c;不进则退。学习如赶路&#xff0c;不能慢一步。 目录 一、项目简介 二、开发技术与环…

计算机网络-华为无线网络配置

前面已经大致了解了无线通信的原理和无线组网的概念&#xff0c;今天来学习无线的配置过程与步骤。 一、无线组网配置流程 在开始配置前复习下前面讲过无线组网有涉及几个设备&#xff0c;AC无线控制器、AP无线接入点、POE交换机。无线组网与有线组网是相对独立的&#xff0c;不…

SpringBoot配置文总结

官网配置手册 官网&#xff1a;https://spring.io/ 选择SpringBoot 选择LEARN 选择 Application Properties 配置MySQL数据库连接 针对Maven而言&#xff0c;会搜索出两个MySQL的连接驱动。 com.mysql mysql-connector-j 比较新&#xff0c;是在mysql mysql-connect…

RK3568平台 设备模型sysfs文件系统

一.什么是 sysfs 文件系统 sysfs 文件系统是 Linux 内核提供的一种虚拟文件系统&#xff0c;用于向用户空间提供内核中设备&#xff0c;驱动程序和其他内核对象的信息。它以一种层次结构的方式组织数据&#xff0c;并将这些数据表示为文件和目录&#xff0c;使得用户空间可以通…

仰暮计划|“​爷爷说这些话的时候眼睛都红着,他那变形的脊柱和瘸拐的双腿都证明他曾为这个家付出了血汗拼尽了全力”

赴一场拾光之旅&#xff0c;集往年回忆碎片 爷爷生于1952年&#xff0c;今年已有七十一了&#xff0c;是河南焦作沁阳北金村的一位地道农民&#xff0c;劳苦一生&#xff0c;如今终于得以颐养天年。许是早年经历过于难忘&#xff0c;爷爷如今与我讲起仍是记忆犹新&#xff0c;…

【机器学习】机器学习流程之收集数据

&#x1f388;个人主页&#xff1a;甜美的江 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;机器学习 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步…

Leetcode刷题笔记题解(C++):590. N 叉树的后序遍历

思路&#xff1a;类似于二叉树的排序&#xff0c;这里需要将子树进行依次递归遍历&#xff0c;前序遍历也与之类似 /* // Definition for a Node. class Node { public:int val;vector<Node*> children;Node() {}Node(int _val) {val _val;}Node(int _val, vector<N…

2024年微信公众号链接爬取

通过输入&#xff08;或文件导入&#xff09;公众号名称&#xff0c;即可爬取该公众号所有历史文章。 通过公众号官方网站调用API&#xff0c;打开开发者工具后发现有 打开后发现有搜索结果的fakeid&#xff0c;这是每个公众号的标识。 点击某公众号后出现 这是具体公众号文章…

Github 2024-02-03 开源项目日报 Top10

根据Github Trendings的统计&#xff0c;今日(2024-02-03统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量Python项目6C项目1TypeScript项目1JavaScript项目1PowerShell项目1Rust项目1 MLflow: 机器学习生命周期平台 …

NLP_Seq2Seq编码器-解码器架构

文章目录 Seq2Seq架构构建简单Seq2Seq架构1.构建实验语料库和词汇表2.生成Seq2Seq训练数据3. 定义编码器和解码器类4.定义Seq2Seq架构5. 训练Seq2Seq架构6.测试Seq2Seq架构 归纳Seq2Seq编码器-解码器架构小结 Seq2Seq架构 起初&#xff0c;人们尝试使用一个独立的RNN来解决这种…

Linux内核单独编译

现在的芯片功能越来越强大&#xff0c;功能也更加的丰富&#xff0c;为了推广自己的产品&#xff0c;一般芯片厂商都会提供一个包含Uboot&#xff0c;Kernel&#xff0c;Rootfs&#xff0c;以及芯片模块功能的SDK。一般在SDK中会有多个文件夹&#xff0c;比如uboot&#xff0c;…

Linux部署Nacos注册中心实现远程访问UI管理界面

Nacos是阿里开放的一款中间件,也是一款服务注册中心&#xff0c;它主要提供三种功能&#xff1a;持久化节点注册&#xff0c;非持久化节点注册和配置管理。 本例通过结合Cpolar内网穿透实现远程访问Nacos 提供的UI (控制台)界面,帮助管理所有的服务和应用的配置 Cpolar内网穿…

【Git版本控制 04】标签管理

目录 一、创建标签 二、查看标签 三、推送标签 四、删除标签 一、创建标签 标签tag&#xff0c;是对某次 commit 的⼀个标识&#xff0c;相当于起了⼀个别名。 相较于难以记住的 commit id &#xff0c; tag 很好的解决这个问题&#xff0c;因为 tag ⼀定要给⼀个让⼈容易…

嵌入式学习Day14 C语言 --- 位运算

位运算 注意&#xff1a;符号位也遵循这个规则 一、按位与(&) 运算规则&#xff1a;一假则假 int a 0x33;a & 0x55;0011 00110101 0101 &----------0001 0001 //0x11 二、按位或(|) 运算规则&#xff1a;一真则真 int a 0x33;a |0x55;0011 00110101 0101 |…

【k8s系列】(202402) 证书apiserver_client_certificate_expiration_seconds

apiserver_client_certificate_expiration_second证书定义的位置&#xff1a;kubernetes/staging/src/k8s.io/apiserver/pkg/authentication/request/x509/x509.go at 244fbf94fd736e94071a77a8b7c91d81163249d4 kubernetes/kubernetes (github.com) apiserver_client_certi…

[机器学习]K-means——聚类算法

一.K-means算法概念 二.代码实现 # 0. 引入依赖 import numpy as np import matplotlib.pyplot as plt # 画图依赖 from sklearn.datasets import make_blobs # 从sklearn中直接生成聚类数据# 1. 数据加载 # 生成&#xff08;n_samples&#xff1a;样本点&#xff0c;centers&…

83 CTF夺旗-Python考点SSTI反序列化字符串

这里写目录标题 CTF各大题型简介演示案例:CTF夺旗-Python-支付逻辑&JWT&反序列化CTF夺旗-Python-Flask&jinja2&SSTl模版注入CTF夺旗-Python-格式化字符串漏洞&读取对象 涉及资源&#xff1a; 我们这篇文章主要讲的是CTF在web渗透测试方向的3个考点 CTF各大…

【C语言】位与移位操作符详解

目录 1.⼆进制和进制转换 ①十进制&#xff1a;生活中最常用 ②二进制&#xff1a;计算机中使用的&#xff0c;每个数字称为一个比特 ③八进制、十六进制也如上 ④二进制转十进制 ⑤十进制转二进制 ⑥二进制转八进制 ⑦二进制转十六进制 2.原码、反码、补码 3.移位操…

计算机网络概念、组成、功能和分类

文章目录 概要1.怎么学习计算机网络2.概念3.功能、组成4.工作方式、功能组成5.分类 概要 概念、组成、功能和分类 1.怎么学习计算机网络 2.概念 通信设备&#xff1a;比如路由器、路由器 线路&#xff1a;将系统和通信设备两者联系的介质之类的 计算机网络是互连的、自治的的计…

【学习笔记】TypeScript学习笔记1 --TypeScript中的类型

文章目录 TS总的变量类型References TS总的变量类型 备注&#xff1a; 如果一个变量设置为了any 类型之后相当于变量关闭了TS的类型检测 let d: any; d 10; d hello;//unknown表示的是未知类型&#xff0c;实际是上一个安全的any,unknown类型的变量不能直接赋值给其他变量le…