c++ - 类与对象 - explicit关键字 | static成员 | 友元 | 内部类 | 匿名对象

文章目录

    • 一、 explicit关键字
    • 二、static成员
    • 三、友元
    • 四、内部类
    • 五、匿名对象


一、 explicit关键字

1、隐式类型转换
再进行隐式类型转换是会产生一个临时变量tmp,再用临时变量进行赋值。

如:

double d = 1.2;
//再用 d 给 i 进行赋值时,会进行隐式类型转换。
//过程:产生 tmp  = 1 ,再用 tmp 给 i 进行赋值
int i = d;

在这里插入图片描述

那么对于类来说是否也能进行这样的隐式类型转换呢?
答:是的,比如 int 转为 类 , 先用 int i 进行转换为 类类型 A(这个过程会调用构造函数进行构造出一个临时类(tmp)),再用 tmp 拷贝到 A 即完成了隐式类型转换。

如:

class A
{
public:
	//有参构造
	A(int a)
		:_a(a)
	{
		cout << "A(int a)" << endl;
	}

	//拷贝构造
	A(const A & a)
	{
		cout << "A(const A & a)" << endl;
	}
private:
	int _a;

};

int main()
{
	A aa = 3;
	//等价与  A tmp(3) , A aa = tmp; 
	//先将 3(int) 隐式转换为 自定义类型 A (tmp),再aa = tmp (拷贝构造)

	return 0;
}

在这里插入图片描述
在这里插入图片描述
上面演示的是单参数的隐式转换,下面是多参数的隐式转换

//多参数隐式类型转换
class A
{
public:
	//有参构造  多参数
	A(int a,int b)
		:_a(a)
		,_b(b)
	{
		cout << "A(int a)" << endl;
	}
private:
	int _a;
	int _b;
};

int main()
{
	//调用格式 ,也可 aa{1,2},但是不建议这种
	A aa = { 1,2 };
	return 0;
}

补充:
临时变量具有常量性。

int main()
{
	double d = 1.12;

	//int i = d; 正常进行隐式转换

	//int& i = d;	//引用临时变量  过程 const int tmp -> int &i = tmp 但是tmp是常量所以会报错 

	//正确做法	//临时变量如果被引用生命周期会延长,不然用完就销毁了
	const int& i = d;
	return 0;
}

在这里插入图片描述

2、如果不想要编译器进行隐式类型转换呢?
使用 explicit 关键字 就可以了
如:

explicit A(int a,int b)
	:_a(a)
	,_b(b)
{
	cout << "A(int a)" << endl;
}

二、static成员

1、概念

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

class A
{
public:
	//静态成员函数
	static void Print()
	{
		cout << _a << endl;
	}

private:
	//静态成员变量
	static int _a;
};

//在类外定义
int A::_a = 10;

2、static成员的特征

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

class A
{
public:
	//静态成员函数
	static void Print()
	{
		cout << _a << endl;
		//静态函数不能访问非静态成员
		//cout << _b << endl;
	}

	//静态成员变量  声明
	static int _a;
	int _b = 10;
};

//在类外定义
int A::_a = 10;

int main()
{
	A a1;
	cout << sizeof(a1) << endl; // 大小为 4 ,_a 存在静态区

	A a2;
	cout << "直接通过类来访问" << A::_a << endl;
	cout << "a1:" << a1._a << endl;		// a1._a == a2._a 这个成员变量共享
	cout << "a2:" << a2._a << endl;		//当前在公共区域,当设置为私有时对象就不可访问了

	return 0;
}

在这里插入图片描述

3、静态和非静态的区别

1、调用方式:
非静态成员函数:需要通过类的实例来调用。
静态成员函数: 可以通过类名直接调用,也可以通过实例调用。
2. 访问成员:
非静态成员函数: 可以访问类的实例中的非静态成员变量和其他成员函数。
静态成员函数: 不能直接访问类的实例成员,只能访问类的静态成员变量和其他静态成员函数。
3. this指针:
非静态成员函数: 隐含地有一个指向当前对象的指针(this指针)。
静态成员函数: 没有this指针,因为它与特定的实例无关。

三、友元

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

关键字:friend

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

(1)如:重载 << 操作符
我们知道 重载 << 操作符时,不能定义为成员函数,所以只能使用全局函数了,但是类的成员变如果是私有的,对象就无法访问成员变量了,这时使用友元函数就可以很好解决这个问题。

class A
{
	//声明友元函数
	friend ostream& operator<<(ostream& _cout, A& a);
public:


private:
	int _a = 10;
};

ostream& operator<<(ostream& _cout, A &a)
{
	//作为友元函数来访问私有成员
	_cout << a._a << endl;
	return _cout;
}

(2)友元函数的特征

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

2、友元类

(1)友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
(2)友元关系是单向的,不具有交换性。
(3)友元关系不能传递 如果C是B的友元, B是A的友元,则不能说明C时A的友元。
(4)友元关系不能继承。

class B;
//友元类
class A
{
	//B 类作为 A类的友元
	friend class B;
public:
	void Print(B& b)
	{
		//A类不可以访问B类 ,不具有交换性
		//cout << b._b << endl;
	}
	

private:
	int _a = 10;
};

class B
{
	friend class C;
public:
	void Print(A& a)
	{
		//可以访问非公有成员
		cout << a._a << endl;
	}
private:
	int _b = 10;
};

class C
{
public:
	void Print(A& a)
	{
		//友元关系不能传递,这里无法访问到A类的非公有成员
		//cout << a._a << endl;
	}
};

四、内部类

1、概念

如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限,但是内部类就是外部类的友元类。

2、特征

(1). 内部类可以定义在外部类的public、protected、private都是可以的,但是也会受到这些作用符限定。
(2)注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。
(3) sizeof(外部类)=外部类,和内部类没有任何关系。

//内部类
class A
{
public:
	//B类 默认作为 A类友元
	class B
	{
	public:
		void P(A& a)
		{
			//可以直接访问a的非公有成员
			cout << a._a << endl;

			//可以直接访问A类的静态成员
			cout << s_a << endl;
		 }

	private:
		int _b = 10;

	};



private:
	int _a = 10;
	static int s_a;
};
int A::s_a = 20;


int main()
{
	A a;

	cout << "A类的大小:" << sizeof(a) << endl; //4,不受到B类的干扰

	//使用B类
	A::B  b;

	//访问b类成员函数
	b.P(a);

	return 0;
}

在这里插入图片描述

五、匿名对象

//匿名对象
class A
{
public:
	A(int a = 10)
		:_a(a) 
	{}
	int get()
	{
		return _a;
	}

private:
	int _a;

};

int main()
{
	//正常实例化对象  生命周期从定义到main函数结束
	A a1;
	A a2(10);

	//匿名对象	生命周期仅仅就是定义这行
	A();
	A(10);

	//一些作用如:想调用非静态成员函数

	//用匿名对象
	A().get();	

	//一般用法  ,比匿名对象繁琐
	A a3;
	a3.get();

	return 0;

}

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

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

相关文章

【Web】AFCTF 2021 题解(部分)

目录 BABY_CSP search secret google authenticator 随便做做&#xff0c;环境是NSS上的 BABY_CSP CSP绕过_script-src self-CSDN博客 CSP指令值 *&#xff1a; 星号表示允许任何URL资源&#xff0c;没有限制&#xff1b; self&#xff1a; 表示仅允许来自同源&#xff…

数据结构-循环队列和循环双端队列的多角度实现

文章目录 1. 循环队列的数组形式实现2. 循环队列的链表实现3. 循环双端队列的数组形式实现4. 循环双端队列的链表实现 在力扣的题面如下 1. 循环队列的数组形式实现 其实循环队列的数组形式只有下面要注意的点,只要掌握了下面的这几点,代码层面上就没有什么问题了 用数组模拟的…

了解 Unity AI:从初学者到高级的综合指南

游戏中的AI是什么? 游戏中的人工智能是指利用人工智能技术使视频游戏中的非玩家角色和实体智能地行动、做出决策、对游戏环境做出反应,并提供引人入胜的动态游戏体验。什么是NPC? NPC 代表“非玩家角色”。NPC 是视频游戏、角色扮演游戏中不受人类玩家控制的角色。它们是计算…

Git 新手快速入门教程

一、什么是 Git 1. 何为版本控制 版本控制是一种记录文件变化的系统&#xff0c;可以跟踪文件的修改历史&#xff0c;并允许用户在不同版本之间进行比较、恢复或合并。它主要用于软件开发过程中管理代码的变更&#xff0c;但也可以应用于任何需要跟踪文件变更的场景。 版本控…

【学习笔记二十一】EWM仓库两步拣配配置及操作展示

一、EWM两步拣配配置 1.定义两步拣配的WPT ①第一步:标准WPT2020,目标仓位是2010两步拣配的仓位,并创建存储类型2010的两步拣配的仓位 ②第二步,标准WPT2010,目标仓位9020发货区和发货的仓位 2.定义确定仓库处理类型的控制标识 3.确定仓库处理类型 4.仓库编码级别需要允…

路由引入、路由策略、路由过滤实验

实验拓扑 实验思路 配置ip地址&#xff0c;配置RIP,OSPF;在R2上分别在RIP下引入OSPF&#xff0c;在OSPF下引入RIP;在R2上配置acl 2000,拒绝R4的业务网段&#xff0c;同时允许其他网段访问&#xff08;acl 2000 默认拒绝网段&#xff09;&#xff1b;通过配置路由过滤router-…

数据分析_数据分析思维(1)

数据分析_数据分析思维(1) 这篇文章具体的给大家介绍数据分析中最为核心的技术之一: 数据分析思维的相关内容。 一、数据分析的三种核心思维 作为新手数据分析师或数据运营, 在面对数据异常的时候, 好多小伙伴都会出现: “好像是A引起的”, “好像也和B渠道有关”, “也可能…

OpenCV与AI深度学习 | OpenCV如何读取仪表中的指针刻度

本文来源公众号“OpenCV与AI深度学习”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;OpenCV如何读取仪表中的指针刻度 最近遇到一个问题&#xff0c;如何读取仪表中的指针指向的刻度。 解决方法有多种&#xff0c;比如&#xff…

队列常规使用

文章目录 一、同步互斥改进方法二、队列实现同步三、队列实现互斥总结 一、同步互斥改进方法 在上一章同步互斥中&#xff0c;我们有两个实验。 同步实验&#xff1a; 我们创建了两个任务&#xff0c;任务1循环遍历一个比较大的数字&#xff0c;遍历完成后设置标志位置1。任务…

如何用网页绘制一个黑莓9900的键盘效果图

如何用网页绘制一个黑莓9900的键盘效果图 入了几个黑莓蓝牙键盘&#xff0c;出于喜好&#xff0c;想做一个跟实体键盘一模一样的网页界面。 最终的实现效果是这样的&#xff1a; 在线查看&#xff1a;http://kylebing.cn/tools/bb-keyboard 点击上面四个按键显示不同模型界面…

PDM在Office文档中的变量映射

在PDM数据管理软件中需要在数据卡中反馈出文件的一些属性信息&#xff0c;使得用户在不打开文件的情况下可以快速了解此文件的属性信息&#xff0c;或者需要用户在创建文档时填入相应内容&#xff0c;能够自动的填充到文档中&#xff0c;所以就需要在实施的过程中在SOLIDWORKS …

[C++][算法基础]求组合数(I)

给定 &#x1d45b; 组询问&#xff0c;每组询问给定两个整数 &#x1d44e;&#xff0c;&#x1d44f;&#xff0c;请你输出 的值。 输入格式 第一行包含整数 &#x1d45b;。 接下来 &#x1d45b; 行&#xff0c;每行包含一组 &#x1d44e; 和 &#x1d44f;。 输出格…

CSS布局 Flex 和 Grid

在 CSS 中&#xff0c;理解 flex 和 Grid 布局非常重要&#xff0c;今天把这两个重要知识点回顾一下。 Flexbox 弹性盒子布局 弹性布局支持 flex、inline-flex&#xff0c;支持块和内联。 容器 轴的概念&#xff0c;在 Flexbox&#xff0c;有主轴和侧轴的概念&#xff0c;轴…

自己写的加密案例4——某东方课程头部sign加密

网址&#xff1a;aHR0cHM6Ly9kc2FwaS54ZGYuY24vcHJvZHVjdC92Mi9jbGFzcy9zZWFyY2g 进行抓包分析&#xff0c;发现请求头中由sign加密&#xff0c;简单判断是消息摘要算法。 Sign:d7c68100ca508bb7c8ae284560754303 进行xhr断点&#xff0c;一下子就发现了位置。 s c.sign&…

“傻瓜”学计量——核密度估计KDE

提纲&#xff1a; 什么是核密度估计&#xff0c;是干什么的 代码 1 前言 参数估计vs非参数估计参数估计是样本数据来自一个具有明确概率密度函数的总体。非参数估计是样本数据的概率分布未知&#xff0c;这时&#xff0c;为了对样本数据进行建模&#xff0c;需要估计样本数据…

嵌入式面试-回答UART

说明&#xff1a; 此文章是在阅读了一些列面试相关资料之后对于一些常见问题的整理&#xff0c;主要针对的是嵌入式软件面试中涉及到的问答&#xff0c;努力精准的抓住重点进行描述。若有不足非常欢迎指出&#xff0c;感谢&#xff01;在总结过程中有些答案没标记参考来源&…

leetcode每日一题第五十六天

今天心情不好&#xff0c;就做一道 class Solution { public:int countTarget(vector<int>& scores, int target) {return help(scores,target)-help(scores,target-1);}int help(vector<int>&scores,int target){int left 0;int right scores.size()-1;…

针对窗口数量多导致窗口大小显示受限制的问题,使用滚动条控制窗口

建议&#xff1a;首先观察结果展示&#xff0c;判断是否可以满足你的需求。 目录 1. 问题分析 2. 解决方案 2.1 界面设计 2.2 生成代码 2.3 源码实现 3. 结果展示 1. 问题分析 项目需要显示的窗口数量颇多&#xff0c;主界面中&#xff0c;如果一次性显示全部窗口&#x…

Spring AOP (一)

本篇主要介绍Spring AOP的基础概念和入门使用 一、AOP的基本概念 AOP是一种面向切面编程的思想&#xff0c;它与IOC并称为Spring 的两大核心思想。什么是面向切面编程呢&#xff0c;具体来说就是对一类事情进行集中统一处理。这听起来像不像前面篇章中所介绍的统一功能处理&am…

❤️新版Linux零基础快速入门到精通——第三部分❤️

❤️新版Linux零基础快速入门到精通——第三部分❤️ 非科班的我&#xff01;Ta&#xff01;还是来了~~~3. Linux权限管控3.1 认知root用户3.1.1 Switch User——su3.1.2 sudo命令3.1.3 为普通用户配置sudo认证 3.2 用户和用户组3.2.1 用户、用户组3.2.2 用户组管理3.2.3 用户管…