C++类和对象(下)

⭐️ 初始化列表

构造函数体内的赋值不能称为初始化,只能将其称为赋值,因为初始化只能初始化一次,而构造函数体内可以多次赋值。
初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个成员变量后面跟一个括号,括号里是当前成员变量的初始值或表达式。

例1:

#include <iostream>	
using namespace std;

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

int main() {

	Date date(2023, 8, 13);

	return 0;
}

ps: 每个成员变量在初始化列表只能初始化一次。类中以下成员必须在初始化列表初始化。

  • 引用成员变量
  • const 成员变量
  • 自定义类型成员(且该类没有默认构造函数的时候)

例2:

#include <iostream>	
using namespace std;

class Time {
public:
	Time(int hour)
		:_hour(hour)
	{}
private:
	int _hour;
};

class Test {
public:
	Test(int num, int ref, int hour)
		:_num(num)
		,_ref(ref)
		,_time(hour)
	{}
private:
	const int _num;
	int& _ref;
	Time _time;
};

int main() {

	int ref = 20;
	Test test(10 , ref , 40);

	return 0;
}

ps: 当类中的成员变量有自定义类型的时候,当前类的构造函数会隐含的调用自定义类型成员变量的默认构造来初始化,但是当你不提供默认构造时,编译器就会报错。解决的办法是我们自己可以显示的去调用它的构造函数,像初始化成员变量推荐使用初始化列表,一些逻辑判断可以放在函数体内。对于自定义类型成员变量一定会先使用初始化列表初始化。

成员变量在类中声明的顺序就是在初始化列表中的初始化顺序,和声明的顺序有关,与初始化列表的顺序无关。

例3:

#include <iostream>	
using namespace std;

class A {
public:
	A(int a)
		:_a1(a)
		, _a2(_a1)
	{}
	void Print() {
		cout << _a1 << " " << _a2 << endl;
	}
private:
	// 先声明 _a2 也就是在初始化列表中会先初始化 _a2
	int _a2;
	int _a1;
};

int main() {

	A aa(1);
	aa.Print();

	return 0;
}

ps: 先声明 _a2 也就是在初始化列表中会先初始化 _a2,所以在初始化列表中先执行_a2(_a1) ,但是此时 _a1 是随机值,所以 _a2 被赋值成随机值,紧接着是 _a1 初始化执行 _a1(a),所以最终 _a1 被赋值为 a 的值。

在这里插入图片描述


⭐️ explicit 关键字

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

例4:

class Date {
public:
	Date(int year)
		:_year(year)
	{}
private:
	int _year;
};

int main() {

	Date d1(2023);	// 直接调用构造函数初始化
	/*
		具有隐式类型转换:
			先使用 2022  构造出一个临时对象
			再拷贝构造给 d2
			但是通常编译器会直接优化成 直接调用构造函数
	*/
	Date d2 = 2024; 

	return 0;
}

ps: 当加上 explicit 关键字修饰构造函数,就会禁止了单参的构造函数类型转换的作用。

在这里插入图片描述


⭐️ static 成员

声明 static 的类成员称为类的静态成员,类静态成员变量一定要再类外进行初始化,static 修饰的变量和函数都属于整个类。

特性:

  • 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区
  • 静态成员必须在类外定义,定义时不需要添加 static 关键字,类中是声明
    • int Type:: count = 0;
  • 类静态成员可以用 类名::静态成员 或者对象.静态成员访问
  • 静态成员函数没有隐藏的 this 指针,不能访问任何非静态成员
  • 静态成员也受访问限定符的限制

例5:

#include <iostream>	
using namespace std;

class Test {
public:
	Test() {
		count++;
	}
	static int getCount() {
		return count;
	}
private:
	static int count;	// 声明
};

int Test::count = 0;	// 初始化

int main() {

	Test t1;
	Test t2;
	cout << Test::getCount() << endl;	// 2

	return 0;
}

⭐️ 友元

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

例6:

#include <iostream>	
using namespace std;

class Test {
	// test函数是 Test 类的友元函数
	friend void test(const Test& t);
public:
	Test(int count)
		: _count(count)
	{}
private:
	int _count;
};

void test(const Test& t) {
	cout << t._count << endl;
}

int main() {

	Test t(100);
	test(t);

	return 0;
}

特性:

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

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的私有成员。

  • 友元是单向的。AB 的友元,那么 A 就可以访问 B 的私有成员,反之不行。
  • 友元关系不能传递。BA 的友元,CB 的友元,但是 C 不是 A 的友元
class Time {
	/*
		声明 Date 是 Time 的友元类,在 Date 类中的所有成员函数都可以访问 Time 类的私有保护成员变量
	*/
	friend class Date;
};

⭐️ 内部类

如果一个类定义在另一个类的内部,这个类就叫做内部类。内部类可以看作是一个独立的类,它不属于外部类,也不能通过外部类的对象去访问内部类的成员,外部类也访问不到内部类的成员。
需要注意的是:

  • 内部类天生就是外部类的友元类,内部类可以通过外部类的对象来访问外部类中的成员。
  • 内部类可以直接访问外部类中的 static 成员,不需要外部类的对象或类名
  • sizeof(外部类) = 外部类 ,和内部类没有任何关系
  • 内部类也会受到访问限定符的限制
  • 内部类会受到外部类的类域限制

例7:

#include <iostream>	
using namespace std;

class A {
private:
     static int _k;
     int _h = 100;
public:
     //B天生就是A的友元
    class B {
    public:
        void foo(const A& a) {
            // 可以直接访问外部类的静态变量
            cout << _k << endl; 
            // 可以直接通过外部类对象访问外部类的私有成员
            cout << a._h << endl;
        }  
    };
};
int A::_k = 1;

int main() {

    // 创建内部类对象 受外部类类域限制
    A::B b;
    // A() 匿名对象 声明周期就在当前行
    b.foo(A());

    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vscode搭建c语言环境问题

c语言环境搭建参考文章:【C语言初级阶段学习1】使用vscode运行C语言&#xff0c;vscode配置环境超详细过程&#xff08;包括安装vscode和MinGW-W64安装及后续配置使用的详细过程&#xff0c;vscode用户代码片段的使用&#xff09;[考研专用]_QAQshift的博客-CSDN博客 问题如下:…

2023国赛数学建模思路 - 复盘:人力资源安排的最优化模型

文章目录 0 赛题思路1 描述2 问题概括3 建模过程3.1 边界说明3.2 符号约定3.3 分析3.4 模型建立3.5 模型求解 4 模型评价与推广5 实现代码 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 描述 …

MySQL中用什么数据类型存IP地址

提到IP地址(IPv4)&#xff0c;我们脑子里肯定立马浮现类似于192.168.0.1、127.0.0.1这种常见的IP地址&#xff0c;然后结合这个问题“MySQL中用什么数据类型存IP地址&#xff1f;”&#xff0c;于是乎脱口而出用char字符串类型存储。 然后再仔细想想发现&#xff0c;这个IP地址…

日常工具 之 一些 / 方便好用 / 免费 / 在线 / 工具整理

日常工具 之 一些 / 方便好用 / 免费 / 在线 / 工具整理 目录 日常工具 之 一些 / 方便好用 / 免费 / 在线 / 工具整理 1、在线Json &#xff0c;可以在线进行json 格式验证&#xff0c;解析转义等操作 2、Gif动图分解&#xff0c;在线把 gif 图分解成一张张单图 3、在线P…

Java一般用于postgis空间数据库通用的增删查改sql命令

目录 1 增加 2 删除 3 查询 4 更新 "public"."JGSQGW_Geo"为某模式下得表 一般postgrel有这样的设计模式 1 增加 #前端绘制出的数据插入 INSERT INTO "public"."JGSQGW_Geo" ( "geom","gridone","gridon…

React Native 列表组件基础知识

ScrollView 组件 ScrollView组件是一个容器滚动组件&#xff0c;当容器超出指定宽高时就可以进行滚动交互。 ScrollView组件是一次性渲染所有的 React 子组件&#xff0c;这在性能上是比较差的&#xff0c;所以不建议当列表特别长的时候使用此组件。 接下来列举几个常用的一…

使用node搭建服务器,前端自己写接口,将vue或react打包后生成的dist目录在本地运行

使用node.jsexpress或者使用node.jspm2搭建服务器&#xff0c;将vue或react打包后生成的dist目录在本地运行 vue项目打包后生成的dist目录如果直接在本地打开index.html,在浏览器中会报错&#xff0c;无法运行起来。 通常我是放到后端搭建的服务上面去运行&#xff0c;当时前端…

Springboot整合RabbitMq,详细使用步骤

Springboot整合RabbitMq&#xff0c;详细使用步骤 1 添加springboot-starter依赖2 添加连接配置3 在启动类上添加开启注解EnableRabbit4 创建RabbitMq的配置类&#xff0c;用于创建交换机&#xff0c;队列&#xff0c;绑定关系等基础信息。5 生产者推送消息6 消费者接收消息7 生…

Win11中使用pip或者Cython报错 —— error: Microsoft Visual C++ 14.0 is required.

第一步&#xff1a;下载Visual Studio 2019 下载地址&#xff1a; https://learn.microsoft.com/zh-cn/visualstudio/releases/2019/release-notes 第二步&#xff1a;安装组件 选择单个组件&#xff0c;勾选以下两个组件 其他错误&#xff1a; 无法打开文件“python37.li…

网络编程(TFTP协议实验)

#include <stdio.h> #include <string.h> #include <stdlib.h> #include <head.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h>#define PORT 69 //端口号&#xf…

16通道AD采集FMC子卡推荐哪些?

FMC149是一款16通道65MHz采样率14位直流耦合AD采集FMC子卡&#xff0c;符合VITA57.1规范&#xff0c;可以作为一个理想的IO模块耦合至FPGA前端&#xff0c;16通道AD通过FMC连接器&#xff08;HPC&#xff09;连接至FPGA从而大大降低了系统信号延迟。 该板卡支持板上可编程采样…

难解的bug

android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord 【Android TimeCat】 解决 context.startforegroundservice() did not then call service.startforeground() | XiChens Blog http://www…

Vue+ElementUI实现选择指定行导出Excel

这里记录一下&#xff0c;今天写项目时 的一个需求&#xff0c;就是通过复选框选中指定行然后导出表格中选中行的Excel表格 然后这里介绍一个工具箱(模板)&#xff1a;vue-element-admin 将它拉取后&#xff0c;运行就可以看到如下界面&#xff1a; 这里面的很多功能都已经实现…

【TypeScript】进阶之路语法细节,类型和函数

进阶之路 类型别名(type)的使用接口(interface)的声明的使用二者区别&#xff1a; 联合类型和交叉类型联合类型交叉类型 类型断言获取DOM元素 非空类型断言字面量类型的使用类型缩小&#xff08;类型收窄&#xff09;TypeScript 函数类型函数类型表达式内部规则检测函数的调用签…

线性规划模型-应用篇

文章目录 模型特点使用技巧工具包和求解器模型线性化 应用实例经验总结 模型特点 上一篇中&#xff0c;详细阐述了线性规划问题和单纯形法的算法原理&#xff0c;本文将着重介绍线性模型在工业场景中的应用。 首先需要说清楚的是&#xff0c;为什么线性模型深受研发人员青睐。…

【dnf5文档】新一代RedHat自动化包管理器

前言 HI,CSDN的码友们&#xff0c;距离上一次我发文章已经过去了半年的时间&#xff0c;现在我又来介绍自己新发现和探究的开源技术了。计算机的发展总是飞速的&#xff0c;当我在写这篇文章的时候&#xff0c;Fedora rawhide已经进入了40版本、默认采用的自动化包管理器为dnf…

iPhone苹果手机触屏失灵无法关机,如何强制重启

参考:https://zhuanlan.zhihu.com/p/615223121 1&#xff0c;只轻按一下音量上键后快速松开 2&#xff0c;只轻按一下音量下键后快速松开 3&#xff0c;只按住右侧电源键长按不松手&#xff0c;直到手机关机。

什么是CSS中的渐变(gradient)?如何使用CSS创建线性渐变和径向渐变?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 渐变&#xff08;Gradient&#xff09;在CSS中的应用⭐ 线性渐变&#xff08;Linear Gradient&#xff09;语法&#xff1a;示例&#xff1a; ⭐ 径向渐变&#xff08;Radial Gradient&#xff09;语法&#xff1a;示例&#xff1a; ⭐ 写…

CentOS安装Postgresql

PG基本安装步骤 安装postgresql&#xff1a; sudo yum install postgresql-server初始化数据库&#xff1a;安装完毕后&#xff0c;需要初始化数据库并创建初始用户&#xff1a; sudo postgresql-setup initdb启动和停止服务&#xff1a; sudo systemctl start postgresql sudo…

FreeRTOS源码分析-12 低功耗管理

目录 1 STM32低功耗管理概念及应用 1.1睡眠模式 1.2 停止模式 1.3 待机模式 2 Tickless低功耗管理 2.1 Tickless低功耗模式介绍 2.2 FreeRTOS低功耗模式配置 2.3 FreeRTOS低功耗模式应用 3 低功耗管理实际项目开发 3.1 低功耗设计必须要掌握的硬件知识 …