你好,C++对象

news2024/11/19 7:47:41

你好,对象

      • 面向对象开发
        • 对象的定义
    • 类与对象
        • 类的定义
        • 类的访问限定符及封装
        • 类的实例化
        • 类对象模型
          • 结构体内存对齐规则
      • this指针
          • this指针的引入
        • this指针的特性
    • 类的默认成员函数
      • 构造函数
      • 析构函数
      • 拷贝构造函数
        • 结语

面向对象开发

对象的定义

对象的含义是指具体的某一个事物,即在现实生活中能够看得见摸得着的事物。
在面向对象程序设计中,对象所指的是计算机系统中的某一个成分。
在面向对象程序设计中,对象包含两个含义,其中一个是数据,另外一个是动作。
对象是数据和动作的结合体。对象不仅能进行操作,同时还能及时记录下操作结果。

C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。

请添加图片描述

类与对象

类的定义

在 C++ 中,我们定义类可以用到structclass这两个关键字,类的组成如下:

class classname//这里classname为自定义类的名字
{
	//类成员变量或成员变量
	//括号内就是类的主体
};//后括号带分号
//struct同理

类中的内容称为类的成员:类中的变量称为类的属性或者成员变量,类中的函数被称为类的方法或者成员函数。

例如我们现在要定义一个以人为原型的类:

  1. 第一种方案是声明和定义全部放在类体中,不过需要注意的是成员函数在类中定义,编译器可能会将其识别成内联函数。
class Person
{
public:
	int _age;
	char _name[50];
	bool _gender;
	//.....

	void Eat()
	{
		//....
	}

	void Play()
	{
		//....
	}

	void Sleep()
	{
		//....
	}
	//.....
};
  1. 第二种方案是成员函数的声明与定义分离,例如test.cctest.h
//对于test.h
class Person
{
public:
	int _age;
	char _name[50];
	bool _gender;
	//.....

	void Eat();
	void Play();
	void Sleep();
	//.....
};
//对于test.cc
void Person::Eat()
{
	//....
}

void Person::Play()
{
	//....
}

void Person::Sleep()
{
	//....
}

需要注意的是,这里在定义函数的时候,需要指明那个类的作用域下的函数,即在函数名前加上Person::,指明该函数服务于Person

我们可以看到_age,_name[50],_gender这三个为成员变量,代表的是人的年龄,名字,性别;而对于void Eat() , void Play() , void Sleep()这三个为成员函数,代表的是人的行为,这就是以人为原型的类。

类的访问限定符及封装

面向对象的三大特性:封装、继承、多态。

封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。

C++实现封装的方式:用类将对象的属性与方法结合在一起,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
访问限定符有三个,分别为public(公有)、protected(保护)、private(私有)

访问限定符说明

  1. public修饰的成员在类外可以被直接访问
  2. protected和private修饰的成员在类外不能被直接访问
  3. 访问权限作用域从访问权限限定符出现的位置到下一个访问权限限定符出现或到’}'为止
  4. class的默认权限为private,struct的默认权限为public(因为struct要兼容C语言)
  5. 访问限定符指只在编译时有用,但数据映射到内存后,没有任何访问限定符上的区别
类的实例化

定义:用类类型创建对象的过程,称为类的实例化。

类的实例化与对象的关系:

1. 类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它
2. 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量
3. 类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图

类对象模型

类对象储存方式:只保存成员变量,成员函数存放在公共的代码段
例如:求下面代码中A内存的大小

//x86环境下
class A
{
	int a;
	char* b;
	char c;

public:
	void x();
	int y();
	void z(int i);
	double v(char* i);
};

由类对象储存方式可知,int 占有4个字节,char* 为x86环境下的指针大小为4,char 占用的字节为1,合计为9,但是在计算机中变量的储存大小应为48的倍数,在x86环境下,默认倍数为4,所以这里A类的内存大小为12.
运行结果如下:
在这里插入图片描述
结论:一个类的大小,实际就是该类中”成员变量”之和,当然要注意内存对齐;注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象。
储存图解如下:
在这里插入图片描述

结构体内存对齐规则

1. 第一个成员在与结构体偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

this指针

this指针的引入

C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

this指针的特性

1. this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。
2. 只能在“成员函数”的内部使用。
3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。
5. this指针储存在栈上,且this指针在不访问成员变量或访问的成员函数中没有成员变量时可以为空。

类的默认成员函数

默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。

构造函数

定义:构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,以保证每个数据成员都有 一个合适的初始值,并且在对象整个生命周期内只调用一次。

特性:构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象。

特征:

1. 函数名与类名相同。
2. 无返回值。
3. 对象实例化时编译器自动调用对应的构造函数。
4. 构造函数可以重载。
5. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。
6. 编译器生成默认的构造函数会对自定类型成员调用的它的默认成员函数。
7. 在C++11之后,内置类型成员变量在类中声明时可以给默认值。
8. 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。
9. 无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。

测试样例:

class Person
{
public:
	int _age;
	char _name[50];
	bool _gender;
	
	Person()
	{
		std::cin >> _age;
		std::cin >> _name;
		std::cin >> _gender;
	}

	void Print()
	{
		std::cout << "age:" << _age << std::endl;
		std::cout << "name:" << _name << std::endl;
		std::cout << "gender:" << _gender << std::endl;
	}
};

int main()
{
	Person p;
	p.Print();
	return 0;
}

我们可以看到这里我们只是定义了一个Person类的p,他就自动调用了我们所定义的构造函数让我们输入,之后我们早调用类pPrint打印p结果。

运行结果如下:
在这里插入图片描述

析构函数

定义
与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。

特征

1. 析构函数名是在类名前加上字符 ~。
2. 无参数无返回值类型。
3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。
4. 析构函数不能重载。
5. 对象生命周期结束时,C++编译系统系统自动调用析构函数。
6. 编译器生成的默认析构函数,对自定类型成员调用它的析构函数。
7. 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数。

测试样例

class Person
{
public:
	int _age;
	char _name[50];
	bool _gender;
	
	Person()
	{
		_age = 17;
		strcpy(_name, "流萤");;
		_gender = 0;
	}

	~Person()
	{
		std::cout << "age:" << _age << std::endl;
		std::cout << "name:" << _name << std::endl;
		std::cout << "gender:" << _gender << std::endl;
	}
};

int main()
{
	Person p;
	return 0;
}

在这里我们可以看到在主函数main中,我们只定义了Person类的p,然后定义时,调用构造函数让成员变量初始化,在主函数main进程结束时销毁栈帧前调用构析函数,对变量中的数据进行打印,就可以得到如下的结果:

在这里插入图片描述
探究
析构函数的调用就相当于栈的调用,即在同一作用域下,先创建的类后销毁也就是后调用析构函数,如下所示:

class Person
{
public:
	int _age;
	char _name[50];
	bool _gender;
	
	Person(const char* x)
	{
		strcpy(_name, x);
	}

	~Person()
	{
		std::cout << _name << std::endl;
	}
};

int main()
{
	Person p1("我老婆");
	Person p2("流萤");
	return 0;
}

我们可以看到在主函数main中,第一次定义了Person类的对象p1,并且将字符"我老婆"传给了p1的构造函数,然后再定义p2,将字符"流萤"传给p2的构造函数。最后return 0函数结束,进行栈帧的销毁。我们可以看到在输出的字符中,流萤是位于第一行,说明 p2先调用析构函数,然后才是p1调用析构函数进行销毁 ,运行结果如下:
在这里插入图片描述
我们再来测试一下,对于不同作用域下构析函数的调用
我们在主函数中定义p1,p2,其中p1,p2的生命周期为主函数,主函数定义的p3用的关键词static修饰被存储在静态区生命周期为整个程序,其中我们也在函数外定义了全局变量p4,p5p4,p5的生命周期也是整个进程,这时就要根据定义的先后和生命周期共同判断先调用谁的构析函数,我们可以看到p1p2的作用域相同,所以他们根据定义的先后来判断谁先调用析构函数。我们可以看到,p2后定义,所以先调用p2p1调用对于p3,p4,p5,他们在静态区存储,但是p4最先定义p3最后定义。所以我们可以得到的销毁顺序是 p2->p1->p3->p5->p4,运行结果如下:
在这里插入图片描述

拷贝构造函数

定义
只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

特征

1. 拷贝构造函数是构造函数的一个重载形式。
2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。
3. 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。
4. 在编译器生成的默认拷贝构造函数中,内置类型是按照字节方式直接拷贝的,而自定义类型是调用其拷贝构造函数完成拷贝的。
5. 类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝构造函数是一定要写的,否则就是浅拷贝。

拷贝构造函数典型调用场景:

1. 使用已存在对象创建新对象
2. 函数参数类型为类类型对象
3. 函数返回值类型为类类型对象

测试样例

class Person
{
public:
	int _age;
	char _name[50];
	bool _gender;
	
	Person(const char* y)
	{
		strcpy(_name, y);
	}

	Person(const Person& x)
	{
		strcpy(_name, x._name);
		std::cout << "Person(const Person& x)" << std::endl;
	}

	~Person()
	{
		std::cout << "name:" << _name << std::endl;
	}
};

int main()
{
	Person p1("流萤");
	Person p2(p1);
	return 0;
}

我们可以看到在定义p1之后,我们又定义了p2,并且将p1拷贝给p2。我们在类中定义了一个拷贝构造函数,并且在调用拷贝构造函数时,我们将打印字符串"Person(const Person& x)"。如下图所示,我们可以看到在拷贝的时候调用了拷贝构造函数,并且打印了"Person(const Person& x)",类中的数据也如愿进行了拷贝,这就是类的默认函数拷贝构造函数的特征。

在这里插入图片描述

结语

以上就是本期的全部内容了,喜欢就多多关注吧!!!

请添加图片描述

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

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

相关文章

NIO-Channel详解

NIO-Channel详解 1.Channel概述 Channel即通道&#xff0c;表示打开IO设备的连接&#xff0c;⽐如打开到⽂件、Socket套接字的连接。在使⽤NIO时&#xff0c;必须要获取⽤于连接IO设备的通道以及⽤于容纳数据的缓冲区。通过操作缓冲区&#xff0c;实现对数据的处理。也就是说…

【大厂AI课学习笔记】1.1.4 学科和学习路径

一、8大学科 特点是特点 &#xff1a;厚基础、重交叉、宽口径。 八大学科分别是&#xff1a;数学与统计、科学与工程、计算机科学与技术、人工智能核心、认知与神经科学、先进机器人技术、人工智能工具与平台。 每个学科&#xff0c;又向下延伸。 MORE: AI&#xff0c;即人…

深度强化学习(王树森)笔记05

深度强化学习&#xff08;DRL&#xff09; 本文是学习笔记&#xff0c;如有侵权&#xff0c;请联系删除。本文在ChatGPT辅助下完成。 参考链接 Deep Reinforcement Learning官方链接&#xff1a;https://github.com/wangshusen/DRL 源代码链接&#xff1a;https://github.c…

【算法与数据结构】139、LeetCode单词拆分

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;本题可以看做一个动态规划问题。其中&#xff0c;字符串s是背包&#xff0c;而字典中的单词就是物品。…

vue 支付宝支付笔记总结

Vue 支付宝支付 1、支付宝介绍 支付宝&#xff08;中国&#xff09;网络技术有限公司成立于2004年&#xff0c;是国内的第三方支付平台&#xff0c;致力于为企业和个人提供“简单、安全、快速、便捷”的支付解决方案。支付宝公司从2004年建立开始&#xff0c;始终以“信任”作…

CTF-PWN-堆-【chunk extend/overlapping-2】(hack.lu ctf 2015 bookstore)

文章目录 hack.lu ctf 2015 bookstore检查IDA源码main函数edit_notedelete_notesubmit .fini_array段劫持(回到main函数的方法)思路python格式化字符串简化思路&#xff1a; exp 佛系getshell 常规getshell hack.lu ctf 2015 bookstore 检查 got表可写&#xff0c;没有地址随…

1、缓存击穿背后的问题

当面试官问&#xff1a;你知道什么是缓存击穿吗&#xff0c;你们是如何解决的&#xff1f; 首先我们要了解什么是缓存击穿&#xff1f;以及缓存击穿会引发什么问题&#xff1f; 缓存击穿就是redis中的热点数据过期&#xff0c;缓存失效&#xff0c;导致大量的请求直接打到数据…

【c++】高精度算法(洛谷刷题2024)玩具谜题详解(含图解)

系列文章目录 第三题&#xff1a;玩具谜题 视频讲解&#xff1a;http://【洛谷题单 - 算法 - 高精度】https://www.bilibili.com/video/BV1Ym4y1s7BD?vd_source66a11ab493493f42b08b31246a932bbb 文章目录 目录 系列文章目录 文章目录 前言 一、题目分析以及思考 二、代码…

伊恩·斯图尔特《改变世界的17个方程》相对论笔记

它告诉我们什么&#xff1f; 物质包含的能量等于其质量乘以光速的平方。 为什么重要&#xff1f; 光的速度很快&#xff0c;它的平方绝对是一个巨大的数。1千克的物质释放出的能量相当于史上最大的核武器爆炸所释放能量的约40%。一系列相关的方程改变了我们对空间、时间、物质和…

C/C++ - 函数进阶(C++)

目录 默认参数 函数重载 内联函数 函数模板 递归函数 回调函数 默认参数 定义 默认参数是在函数声明或定义中指定的具有默认值的函数参数。默认参数允许在调用函数时可以省略对应的参数&#xff0c;使用默认值进行替代。 使用 默认参数可以用于全局函数和成员函数。默认参…

WebRTC 入门:开启实时通信的新篇章(上)

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

使用电脑时突然遇到“mfc140.dll文件丢失”的问题都有什么解决办法

当你在使用电脑时突然遇到“mfc140.dll文件丢失”的问题时&#xff0c;可能会感到困惑和苦恼。一旦出现这样的问题&#xff0c;缺少这个文件可能导致一些应用程序无法正常启动&#xff0c;影响你的工作和娱乐体验。其实这个问题是可以解决的&#xff0c;接下来我们将介绍一些可…

部署个人知识库管理软件 MrDoc详细教程

效果 一、拉取 MrDoc 代码 进入目录&#xff1a; cd /opt开源版&#xff1a; git clone https://gitee.com/zmister/MrDoc.git专业版&#xff1a; git clone https://{用户名}:{密码}git.mrdoc.pro/MrDoc/MrDocPro.git二、拉取 Docker 镜像 docker pull zmister/mrdoc:v7三…

yarn安装第三方插件包,提示报错,yarn的镜像源已经过期了,因为yarn和npm用的是淘宝的镜像源,淘宝的镜像源已经过期了,要设置最新的淘宝镜像源。

淘宝最新镜像源切换_淘宝镜像-CSDN博客 查看yarn用的什么镜像源 yarn config get registry 查看具体的信息 yarn config list 设置淘宝的最新镜像源&#xff0c;yarn和npm都要设置最新的淘宝镜像源&#xff0c;不然还是报错 npm config set registry https://registry.npmm…

211毕业38岁产品经理被裁瞒着妻子送外卖

估计很多人都看到这个新闻了&#xff0c;微博和知乎也都上了热搜榜。 有人说&#xff0c;这一看就是摆拍的&#xff0c;谁没事在家里装个摄像头啊&#xff0c;这两人演技也还差点意思。 也有人说&#xff0c;大丈夫能屈能伸。虽然211毕业在互联网大厂工作&#xff0c;但是被裁了…

代码随想录算法训练营Day42|0-1背包理论基础、416. 分割等和子集

目录 0-1背包理论基础 0-1背包问题 二维dp数组01背包 算法实现 一维dp数组01背包 ​编辑算法实现 416. 分割等和子集 前言 思路 算法实现 总结 0-1背包理论基础 0-1背包问题 题目链接https://kamacoder.com/problempage.php?pid1046 有n件物品…

一、Kotlin 开发环境搭建

1. Kotlin 官网 https://kotlinlang.org/ 2. Kotlin 命令行工具下载 下载网址&#xff1a; https://github.com/JetBrains/kotlin/releases/tag/v1.3.50 切换其他版本&#xff0c;改下版本号即可 下载 kotlin-compiler-1.3.50.zip 文件即可 解压 kotlin-compiler-1.3.50.zip…

【智能家居入门之环境信息监测】(STM32、ONENET云平台、微信小程序、HTTP协议)

作为入门本篇只实现微信小程序接收下位机上传的数据&#xff0c;之后会持续发布如下项目&#xff1a;①可以实现微信小程序控制下位机动作&#xff0c;真正意义上的智能家居&#xff1b;②将网络通讯协议换成MQTT协议再实现上述功能&#xff0c;此时的服务器也不再是ONENET&…

回归预测 | MATLAB实现PSO-GRNN粒子群优化广义回归神经网络多输入单输出预测(含优化前后预测可视化)

回归预测 | MATLAB实现PSO-GRNN粒子群优化广义回归神经网络多输入单输出预测 目录 回归预测 | MATLAB实现PSO-GRNN粒子群优化广义回归神经网络多输入单输出预测预测效果基本介绍程序设计参考资料预测效果 <

Cesium.js实现显示点位对应的自定义信息弹窗(数据面板)

零、相关技术选型&#xff1a; Vue2 Vuecli5 Cesium.js 天地图 一、需求说明 在使用2D地图&#xff08;天地图、高德地图等&#xff09;基于官方文档可以实现下面需求&#xff1a; 实现添加点位&#xff0c;并在点位附近显示对应的信息弹窗。 一般信息弹窗的显示方式有两种&am…