类和对象【C++】【下篇】

news2024/11/23 11:09:01

目录

一、初始化列表

二、隐式类型转换 

三、静态成员

 四、友元

1、友元函数

2、友元类

五、内部类

 六、匿名对象


一、初始化列表

下面是日期类的一个构造函数,调用该构造函数后,对象中已经有了一个初始值,但并不能将它称为对对象成员变量的初始化,构造函数体中的语句只能将其称为赋初值,而不是初始化,因为初始化只能有一次,但构造函数体内可以有多次赋值。

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

 初始化列表:以一个冒号开始,接着是以逗号分隔数据成员列表,每个成员变量后跟一个放在括号内的初始值或表达式

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

 注意,类中包含下列成员,必须放在初始化列表位置进行初始化

(1)引用成员变量(特征:必须在定义的时候初始化)

(2)const修饰的成员变量(特征:必须在定义的时候初始化)

(3)自定义类型成员(且该类没有默认构造函数时)

如果自定义类型没有默认构造函数(无参、全缺省、编译器自动生成的构造函数都叫默认构造函数)时,没有进行初始化,编译器就会报错,如下: 

class A
{
public:
	A(int a)
		:_a(1)
	{}
private:
	int _a;
};
class B
{
public:
	//初始化列表:对象的成员定义的位置

	B(int a, int& ref)
		:_ref(ref)
		,_n(1)
	{}
private:
	int& _ref;//引用
	const int _n;//const

	A _aobj;//没有默认构造函数
	int x = 1;//缺省值,初始化列表没写时,会用缺省值
};
int main()
{
    int n=10;
	B bb1(12, n);//对象整体定义
	return 0;
}

 

因此,我们要在初始化列表对其进行手动初始化: 

	B(int a, int ref)
		:_ref(ref)
		,_n(1)
		,_aobj(1)//调用对象_aobj的构造函数
	{}

 如果一个类中有自定义类型的成员变量,不论你是否使用初始化列表,这些自定义类型的成员变量都会先使用默认构造函数进行初始化。

如果需要自定义初始化这些成员变量,那么只有在构造函数的初始化列表中进行初始化才是有效的。

初始化列表并不能完全取代函数体,举例,对于_a的malloc的检查就需要在函数体内检查。

class Stack
{
public:
	Stack(int capacity = 10)
		: _top(0)
		,capacity(capacity)
		,_a((int*)malloc(capacity * sizeof(int)))
	{
		if (nullptr == _a)
		{
			perror("malloc fail");
			return;
		}
	}

private:
	int capacity;
	int _top;
	int* _a;
};

成员变量在类中的声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关。如上面的代码如果把成员变量定义顺序改成下面这样,就会出问题。

class Stack
{
public:
	Stack(int capacity = 10)
		: _top(0)
		,capacity(capacity)
		,_a((int*)malloc(capacity * sizeof(int)))
	{
		if (nullptr == _a)
		{
			perror("malloc fail");
			return;
		}
	}

private:
	int* _a;//按这个顺序
	int capacity;
	int _top;
};

二、隐式类型转换 

int i=10;
double d = i;
double& d = i;//不可以
const double& d = i;//可以

上面这行代码发生了隐式类型转换,i赋值给d时,会先产生一个具有常属性的临时变量,再将该变量赋给d。

由于这个临时变量具有常属性,所以不能double& d = i ;因为从一个具有const属性的临时变量到double&是权限放大。

像const double& d = i;这样才是可行的。

A aa1 = 2;
A& aa2 = 2;//不可
const A& aa2 = 2;//可以

 同理,如果是A aa1 = 2;

会先用2构造一个临时对象,再将临时对象拷贝赋值给aa1(但是现在的编译器大概率会将其优化,直接用2进行构造)

拷贝对象时的一些编译器的优化:

在传参和传返回值的过程中,一般编译器会做一些优化,减少对象的拷贝,这个在一些场景下是非常有用的。

一个表达式中,连续构造+拷贝构造->优化为直接构造

f1(1);

一个表达式中,连续构造+拷贝构造->优化一个拷贝构造

f1(A(2));

一个表达式中,连续拷贝构造+拷贝构造->优化一个拷贝构造

A aa2 = f2();

 一个表达式中,连续拷贝构造+赋值重载->无法优化

aa1 = f2();

三、静态成员

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

特性:

(1)静态成员为所有类对象共享不属于某个具体的对象,存放在静态区。

(2)静态成员变量必须在类外定义定义时不添加static关键字类中只是声明

(3)类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问。

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

(5)静态成员也是类的成员,受public、protected、private访问限定符的限制。 

(6)成员变量:属于每个类对象,存储在对象里面。

静态成员变量:属于类,属于类的每个对象共享,存储在静态区,它的声明周期是全局的。

(7)静态成员变量不能给缺省值。

非静态成员函数可以调用静态成员函数。

静态成员函数不能调用非静态成员函数,因为静态成员函数没有this指针。

例题:实现一个类,计算类中定义了多少个类对象。 

class A
{
public:
	A()
	{
		++_scount;
	}
	A(const A&t) {
		++_scount;
	}
	~A() {
		--_scount;
	}
	static int GetACount()
	{
        //_a++;无法访问非静态成员,因为没有this指针
		return _scount;
	}
private:
	static int _scount;//声明
    //static int _scount = 1;不可以给缺省值
    int _b;
};
int A::_scount = 0;//类外定义
int main()
{
	cout << A::GetACount() << endl;
	A a1, a2;
	A a3(a1);
	cout << A::GetACount() << endl;
	return 0;
}

静态成员函数引用场景举例:

如果 要你设计一个类,且在类外面只能在栈区上创建对象

或者 要你设计一个类,且在类外面只能在堆区上创建对象

class A
{
public:
	static A GetStackobj()
	{
		A aa;//栈
		return aa;
	}
	static A* GetHeapobj()
	{
		return new A;//堆
	}
private:
	A()
	{}
	int _a = 1;
};
int main()
{
	A::GetHeapobj();
	A::GetStackobj();
	return 0;
}

 四、友元

友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。

友元分为:友元函数和友元类

1、友元函数

问题:现在尝试去重载operator<<,然后发现没办法将operator<<重载成成员函数。因为cout的输出流对象和隐含的this指针在抢占第一个参数的位置。this指针默认是第一个参数也就是左操作数了。但是实际使用中cout需要是第一个形参对象,才能正常使用。、

所以要将operator<<重载成全局函数。但又会导致类外没办法访问成员,此时需要友元来解决。operator>>同理。详细代码参考上期博文。

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

友元函数可以访问类的私有成员和保护成员,但不是类的成员函数

友元函数不能用const修饰

友元函数可以在类定义的任何地方声明,不受类访问限定符的限制

友元函数的调用与普通函数的调用原理相同

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

ostream& operator <<(ostream& out, const Date& d)
{
	out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
	return out;
}

2、友元类

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

注意:

1、友元关系是单向的。

2、友元关系不能传递。

3、友元关系不能继承。

五、内部类

定义在类内部的类,就叫内部类。

内部类是一个独立的类,不属于外部类,不能通过外部类去访问内部类的成员。外部类对内部类没有任何优越的访问权限。

内部类就是外部类的友元类,所以内部类可以通过外部类的对象参数来访问外部类中的使用成员,但是外部类不是内部类的友元。

(1)内部类可以定义在外部类的public、private、protected

(2)内部类可以直接访问外部类中的static成员,不需要外部类的对象\类名

(3)sizeof(外部类)=外部类,和内部类没有任何关系。

 六、匿名对象

有名对象生命周期在当前函数的局部域。

匿名对象的生命周期在当前行。

 因为匿名对象具有常性,所以不能直接引用,但可以这样:

 虽然匿名对象的作用域只在当前行,但由于const引用会延长匿名对象的生命周期(延长到当前函数局部`域),所以ra并不是野引用。

class Solution
{
public:
	int Sum_Solution(int n)
	{
		cout << "sums" << endl;
		return n;
	}
};
int main()
{
	Solution s1;
	s1.Sum_Solution(10);
	Solution().Sum_Solution(20);//匿名对象调用函数
	return 0;
}

 

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

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

相关文章

实时操作系统内存管理-TLSF算法

内存管理-TLSF算法 前言TLSF算法&#xff1a;为什么内存又叫内存“块”&#xff1a;O(1)查找空闲块&#xff1a;确定fl&#xff1a;确定sl&#xff1a;提级申请&#xff1a;分割块&#xff1a; 空闲块如何串成链表&#xff1f;减少外部碎片&#xff1a;查找上下块&#xff1a; …

Java补充之MySQL入门必备知识

文章和代码已经归档至【Github仓库&#xff1a;https://github.com/timerring/java-tutorial 】或者公众号【AIShareLab】回复 java 也可获取。 文章目录 零基础学MySQL解决之道文件、数据库MySQL 数据库的安装和配置使用命令行窗口连接MYSQL 数据库操作示意图 数据库三层结构数…

使用Intellij IDEA创建新项目时,maven路径总是默认的,一创建maven就卡死

目录 使用Intellij IDEA创建新项目时&#xff0c;maven路径总是默认的 弄了老半天&#xff0c;终于把这个破玩意给弄好了&#xff0c;真的没有意思&#xff0c;真的很恶心 我经历了两个过程&#xff0c;一个是 使用Intellij IDEA创建新项目时&#xff0c;maven路径总是默认的…

用免费蜜罐工具配置Modbus工控蜜罐

导语&#xff1a;本文将用DecoyMini免费蜜罐工具来配置自定义的ModbusTCP工控仿真模板&#xff0c;并介绍部署后的Modbus蜜罐的使用效果。 DecoyMini是一个免费的蜜罐工具&#xff0c;其特色是仿真能力采用与软件松耦合的仿真模板来进行管理。通过一键式导入云端仿真模板库里的…

【Linux】多线程 --- 线程同步与互斥+生产消费模型

人生总是那么痛苦吗&#xff1f;还是只有小时候是这样&#xff1f; —总是如此 文章目录 一、线程互斥1.多线程共享资源访问的不安全问题2.提出解决方案&#xff1a;加锁&#xff08;局部和静态锁的两种初始化/销毁方案&#xff09;2.1 对于锁的初步理解和实现2.2 局部和全局锁…

计算机中丢失msvcr120.dll怎么办,电脑找不到msvcr120.dll怎么办

电脑提示msvcr120.dll丢失是一个常见的问题&#xff0c;这个问题通常会在你尝试打开某些程序或游戏时出现。这个问题的原因是因为你的电脑缺少了一个名为msvcr120.dll的文件&#xff0c;这个文件是微软Visual C Redistrle for Visualv 2013的一部分。如果你遇到了这个问题&…

算法设计 || 第5题:田忌赛马-杭州电子科技大学(贪心算法)

目录 &#xff08;一&#xff09;杭电原题 &#xff08;二&#xff09;Please speak Chinese: &#xff08;三&#xff09;手写草稿理解思路核心算法 第一款代码&#xff1a; 第二款代码&#xff1a; &#xff08;一&#xff09;杭电原题 Tian Ji -- The Horse Racing Pro…

【分治法】

目录 知识框架No.1 分治法基本思想No.2 合并排序No.3 快速排序一、基本思想三、效率分析四、快速排序不稳定例子 No.4 二叉树遍历及其相关特性一、基本概念二、中序遍历三、前序遍历四、二叉树的高度计算(高度不是深度) 知识框架 No.1 分治法基本思想 将规模为N的问题分解为k…

Spring MVC:常用参数(注解)的使用和参数绑定的验证

Spring MVC&#xff1a;常用参数&#xff08;注解&#xff09;的使用和参数绑定的验证 一、学习资源二、基础源码三、实验结果3.1 Spring MVC常用参数Controller和RequestMappingRequestMappingRequestParamPathVariableCookie ValueRequestHeader 3.2 Spring MVC参数绑定3.2.1…

一路对标顶级产品,奇遇XR为何仍不见起色?

临近6月&#xff0c;再度遇冷的XR行业&#xff0c;又让很多人充满期待。外界普遍认为&#xff0c;基于苹果酝酿多年的MR头显产品&#xff0c;将于6月举行的WWDC 2023全球开发者大会正式亮相&#xff0c;XR行业或将迎来“iPhone时刻”。 在一派期待中&#xff0c;一家国内XR企业…

代码审计之PHP基础铺垫

目录 1、标记 2、注释 3、输出语句 4、关键字 5、常量的定义与使用 6、预定义常量 7、变量的赋值&#xff08;传参赋值与引用赋值&#xff09; 8、可变变量 9、双引号和单引号的区别 10、heredoc结构和nowdoc结构 11、其他符号 1、标记 <?php 和 ?> 是PHP标…

第十一届蓝桥杯青少组省赛Python中/高级组编程题真题,包含答案解析

第十一届蓝桥杯青少组省赛Python中/高级组编程题真题 编程实现 第一题&#xff1a; 输入一个字符串&#xff0c;如果该字符串以er、Iy或者ing后缀结尾的&#xff0c;则删除该字符串后缀&#xff0c;并输出删除后的字符串&#xff0c;否者将原字符串输出。 输入描述 输入一个…

零知识证明:应用和具体用例

零知识证明&#xff08;Zero-Knowledge Proofs&#xff0c;ZKPs&#xff09;是应用密码学中令人兴奋的突破&#xff0c;将在各个行业中解锁新的用例&#xff0c;从 Web3 到供应链再到物联网。通过在不揭示信息的情况下验证其真实性&#xff0c;ZKPs 可以增强数字系统的隐私、安…

【Unity-UGUI控件全面解析】| Slider 滑动条组件详解

🎬【Unity-UGUI控件全面解析】| Slider 滑动条组件详解一、组件介绍二、组件属性面板三、代码操作组件四、组件常用方法示例4.1 充当 进度条控制灯光亮度4.2 模拟 血条 使用💯总结🎬 博客主页:https://xiaoy.blog.csdn.net 🎥 本文由 呆呆敲代码的小Y 原创,首发于 CS…

【Spring全家桶系列】面向切面编程AOP

⭐️前面的话⭐️ 本文已经收录到《Spring框架全家桶系列》专栏&#xff0c;本文将介绍面向切面编程的思想和相关概念&#xff0c;附加一个小案例。 &#x1f4d2;博客主页&#xff1a;未见花闻的博客主页 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&a…

基于Kubernetes集群构建大中型企业CICD应用平台(2)--code阶段工具gitlab安装

这里我们为gitlab服务器准备一台虚拟机&#xff1a;192.168.19.6-gitlab服务器 在code阶段&#xff0c;我们需要将不同版本的代码存储到一个仓库中&#xff0c;常见的版本控制工具就是SVN或者Git&#xff0c;这里我们采用Git作为版本控制工具&#xff0c;GitLab作为远程仓库。…

django常用命令/vue-cli图形化界面创建方式/vueo-cli命令行创建方式/若依框架/elementui

django常用命令 django-admin.exe startproject mysite python .\manage.py startapp app01 python manage.py makemigrations python manage.py migrate python manage.py runserver python manage.py runserver 0.0.0.0:8000 from django.shortcuts import render,Http…

【Linux学习】多线程——同步 | 条件变量 | 基于阻塞队列的生产者消费者模型

多线程——同步 | 条件变量 | 基于阻塞队列的生成者消费者模型 &#x1f3d3;生产者消费者模型&#x1f3f8;同步概念&#x1f3f8;生产者消费者模型的特点 &#x1f3d3;同步的应用&#x1f3f8;条件变量&#x1f3f8;条件变量接口 &#x1f3d3;基于阻塞队列的生产者消费者模…

文心一言 VS chatgpt (16)-- 算法导论4.1 1~2题

一、当A的所有元素均为负数时&#xff0c;FIND-MAXIMUM-SUBARRAY返回什么? 文心一言&#xff1a; 当A的所有元素均为负数时&#xff0c;FIND-MAXIMUM-SUBARRAY返回-1。 这是因为在二进制中&#xff0c;当所有元素均为负数时&#xff0c;A的每个元素都对应一个负数&#xff…

基于Kubernetes集群构建大中型企业CICD应用平台(4)--Operate阶段工具

还是在192.168.19.7-CentOS-7.6-jenkins-new这台服务器上进行操作 部署过程&#xff0c;会采用Docker进行部署&#xff0c;暂时只安装Docker即可&#xff0c;后续还需安装Kubenetes 4.1 Docker安装 准备测试环境&生产环境 下载Docker依赖组件 # yum -y install yum-uti…