当前位置: 首页 > news >正文

【从小白到大白03】类和对象-下

image-20221014123349140

文章目录

  • explicit关键字
      • 用explicit修饰构造函数,将会禁止构造函数的隐式转换
  • static成员
  • 友员
      • 友元函数
      • 友元类
  • 内部类(类中类)
  • 匿名对象
  • 拷贝对象的编译器优化
  • 如果以上内容对你有帮助的话,不妨点个👍鼓励一下博主吧~~~

explicit关键字

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

image-20221014093802622

image-20221014094608836

对于多个参数的构造函数也支持类型转换的作用!(c++11开始支持)

image-20221014095449114

用explicit修饰构造函数,将会禁止构造函数的隐式转换

image-20221014094031673

static成员

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

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

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

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

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

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

下面的代码段里包含我对static成员的理解

//局部变量-局部作用域-栈
//全局变量-全局域
// 类变量-类域
//
//全局static-作用域:全局
//局部static-作用域:局部
// 类static-作用域:类    ||static成员变量:属于类,且类的每个对象共享
// 这三类的生命周期-全局
//
class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		++N;
	}
//静态成员函数:没有this指针,只能访问静态成员
static	int GetN()
	{
		return N;
	}
	A(const A& aa)
		:_a(aa._a)
	{
		++N;
	}

private:
	int _a;
	//生命周期是全局的,但作用域是类域-保护N不被修改
	static int N;//声明
};
//定义-不需要static修饰
int A::N = 0;
void F1(A aa)//传值传参-拷贝构造//引用返回-不构造
{
}

A F2()
{
	A aa;//调用A的构造函数-构造aa
	return aa;//返回A类型-拷贝构造一份临时变量返回
}
int main()
{
	A aa1(1);//构造-1
	//A aa2 = 2;//构造-1
	//	A aa3 = aa1;//拷贝构造-1
	
	F1(aa1);//拷贝构造-1

	//F2();//构造+拷贝构造-2
	//cout << A::N << endl;//N为类中公有对象可以这样访问
	
	//cout << aa1.N << endl;//N为类中公有对象可以这样访问
	 
	// A*ptr=&aa1(nullptr);
	// cout<<ptr->N<<endl;//N为类中公有对象可以这样访问
	
	//cout << aa1.GetN() << endl;//在对象aa1的类里面找GetN()(访问N)-但必须要构造一个aa1对象(使用了构造函数)
//cout << A::GetN() << endl;//不用定义对象,直接在A类里面找GetN()(访问N)
    //类里面GetN()用static修饰成为静态成员函数后不受类域显示(没有this指针)-可以访问类内静态成员
}

友员

友元函数

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

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

2.友元函数不能用const修饰(友元函数没有this指针)

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

4.一个函数可以是多个类的友元函数

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

image-20221014110801420

友元类

1.友元关系是单向的,不具有交换性。

2.友元关系不能传递

3.友元关系不能继承

class floort
{
	friend class door;//声明door类函数是floort类函数的友元函数,door类函数可以访问floort类函数的私有成员
public:
	floort (int floor = 1)
		:_floor(floor)
	{}
private:
	int _floor;
};
class door
{
public:
	door(int door = 1)
		:_door(door)
	{}
	void findfloor(int door,int floor)
	{
		_t._floor = floor;//直接访问floort类的私有成员变量(floor)
		_door = door;
	}
private:
	int _door;
	floort _t;
};

内部类(类中类)

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

注意:内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。

在【外部】类(类A)外面访问内部类(类B)(类中类)必须要通过【外部】类(类A)-限制

  1. 内部类可以定义在外部类的public、protected、private都是可以的。

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

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

class A
{
public:
	//B天生是A的友元-可以访问A中的所有成员
	class B
	{
		int _b;
	};
private:
	int _a;
};

int main()
{
	cout << sizeof(A) << endl;//4个字节-只有_a的大小 ,B类中_b的大小不沾边
	A aa;
		//	B bb;//不可以
		A::B bb;//可以-访问B必须要通过A
	return 0;
}

匿名对象

匿名对象的构造函数和析构函数的调用在同一行(调用完构造函数后自动调用析构函数)

class A {
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "调用构造函数 A(int a)" << endl;
	}

	~A()
	{
		cout << "调用析构函数~A()" << endl;
	}
private:
	int _a;
};
class Solution {
public:
	int Sum_Solution(int n) {
		//...
		return n;
	}
};

A F()
{
	//A tmp(10);
//	return tmp;
	return A(10);//匿名对象-上面两行合并成这一行
}
int main()
{//有名对象-生命周期局部域-main函数的域-析构函数在main函数末尾时调用
	//A aa1(1);
	//A aa2=aa1;

	//匿名对象-生命周期只在这一行-析构函数在这一行结束时调用
//	A();

//	A aa3;aa3 = 3;
//	A(3);//匿名对象-上面这行合并成这行
	return 0;
}

拷贝对象的编译器优化

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

class A {
public:
	A(int a = 0)//构造函数
		:_a(a)
	{
		cout << "调用构造函数A(int a)" << endl;
	}
	A(const A& aa)
		:_a(aa._a)
	{
		cout << "调用拷贝构造函数A(const A& aa)" << endl;
	}
		A& operator=(const A& aa)
	{
		cout << "调用运算符重载函数A& operator=(const A& aa)" << endl;
		if (this != &aa)
		{
			_a = aa._a;
		}
		return *this;
	}
	~A()
	{
		cout << "调用析构函数~A()" << endl;
	}
private:
	int _a;
};
void f1(A aa)
{}
A f2()//传值返回
{
	A aa;//构造
	return aa;//拷贝构造
}

A  f3()
{
	return A(10);
}
int main()
{
	//A aa1 = 1;//A tmp(1) +A aa1(1)->优化为A aa1(1) ---构造+拷贝构造->构造
	//A aa1;
	//f1(aa1);//这两行是构造+拷贝构造
	//f1(A(1));//构造+拷贝构造->优化:构造

	//f2();//构造+拷贝构造
	//A tmp = f2();//构造+拷贝构造+拷贝构造->优化:构造+拷贝构造
	A tmp1 = f3();//构造+拷贝构造+拷贝构造->优化:构造
	return 0;
}

image-20221014121708522

image-20221014121722170

如果以上内容对你有帮助的话,不妨点个👍鼓励一下博主吧~~~

相关文章:

  • [DAX] MAX函数 | MAXX函数
  • Pytorch实战 | 第4天:猴痘病识别
  • 【C ++基础】第五篇 类和对象 日期计算器
  • SpringBoot+Vue实现前后端分离大学信息及院校推荐网站
  • 编程初学者如何缓解迷茫和焦虑?墙裂推荐此文,助你赢在起跑线
  • [创业之路-42] 创业是只有一小部分人活下来的游戏,探究创业失败的20个主要原因与提高成功率
  • FPGA实现SPI协议
  • 2022年金砖国家职业技能大赛(决赛)网络空间安全赛项 | 浙江赛区选拔赛 任务书
  • 第8章 聚合函数
  • Turbot4机器人入门教程-应用-读取图片文件并发布图像话题
  • Redis的性能优化一些方案
  • 你可能不知道的CSS特征查询
  • 【pygame】之小球基础
  • C++ Reference: Standard C++ Library reference: C Library: cstdarg: va_arg
  • Eclipse技巧(一):快速定位文件的层级位置 | 快速查找文件在工程根目录的位置
  • JavaScript 如何正确处理 Unicode 编码问题!
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • 【跃迁之路】【735天】程序员高效学习方法论探索系列(实验阶段492-2019.2.25)...
  • CSS进阶篇--用CSS开启硬件加速来提高网站性能
  • Java超时控制的实现
  • js正则,这点儿就够用了
  • php ci框架整合银盛支付
  • Python连接Oracle
  • React的组件模式
  • Swoft 源码剖析 - 代码自动更新机制
  • 从PHP迁移至Golang - 基础篇
  • 码农张的Bug人生 - 初来乍到
  • 你真的知道 == 和 equals 的区别吗?
  • 判断客户端类型,Android,iOS,PC
  • 使用docker-compose进行多节点部署
  • 移动端唤起键盘时取消position:fixed定位
  • 在electron中实现跨域请求,无需更改服务器端设置
  • ​VRRP 虚拟路由冗余协议(华为)
  • ​渐进式Web应用PWA的未来
  • ​业务双活的数据切换思路设计(下)
  • # centos7下FFmpeg环境部署记录
  • #Spring-boot高级
  • $.extend({},旧的,新的);合并对象,后面的覆盖前面的
  • (1)(1.13) SiK无线电高级配置(六)
  • (1)常见O(n^2)排序算法解析
  • (env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (剑指Offer)面试题34:丑数
  • (六) ES6 新特性 —— 迭代器(iterator)
  • (十二)springboot实战——SSE服务推送事件案例实现
  • (十一)手动添加用户和文件的特殊权限
  • (五)大数据实战——使用模板虚拟机实现hadoop集群虚拟机克隆及网络相关配置
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • (转)C#调用WebService 基础
  • (转)Mysql的优化设置
  • (转载)跟我一起学习VIM - The Life Changing Editor
  • (轉貼) 蒼井そら挑戰筋肉擂台 (Misc)
  • .gitignore文件_Git:.gitignore
  • .net 受管制代码