cpp从0到1---类与对象1

什么是类

首先要知道cpp和c语言的区别,c语言是面向过程的,而cpp是面向对象的,面向对象的特性就有:封装,继承和多态,这里的封装,就是封装类;
究竟什么是类,比如现在在一个学校,需要管理学生的信息,学生的信息是由姓名,学号,性别,联系方式来定义一个学生的信息;将这些可以表示学生的特征封装起来,就是一个类;
我们在c语言中,会用struct定义一个结构体,这个结构体其实就是一个简单的“类”
比如定义一个学生类:

struct suudent_t
{
	char name[20];
	char sex[5];
	int identity;
	int telephone;
};

这就是一个简单的学生类,而我们用这里的student_t创建出来的变量,就是类类型创建的对象;

student_t stu1,stu2;

这里的stu1和stu2就是student_t创建的两个对象,类和对象的关系可以理解成:
类是对象属性的描述,对象是类的具体实现;

如何定义类

class关键字:
上面的学生类在cpp中可以定义成:

class student_t
{
	string name;
	string sex;
	int identity;
	int telephone;
	
	void SetStudent(string s, string gender, int n1, int n2)
	{
		name = s;
		sex = gender;
		identity = n1;
		telephone = n2;
	}
}

这里可以直接在源文件里面定义,也可以在头文件中声明类,在源文件中定义类

如果要采用第二种方式定义类的话,就得在头文件student.h中写成:

#pragma once
class student_t
{
	string name;
	string sex;
	int identity;
	int telephone;
	
	void SetStudent(string s, string gender, int n1, int n2);
	///函数做简单声明
}

在源文件中

#include "student.h"
void student_t::SetStudent(string s, string gender, int n1, int n2)
{
		name = s;
		sex = gender;
		identity = n1;
		telephone = n2;
}

这里就多了个作用域,因为类也是个作用域;所以在类外定义函数的时候需要用::

访问限定符

在c语言或者是cpp中我们用struct定义一个类,都可以在类外自由的访问它的变量;但是如果用class定义就不一样了
在这里插入图片描述
发现这里就行不通,为什么用class定义的类无法在类外访问变量?

访问限定符:
1、private
2、public
3、protected

protected类的在这里暂时不做讨论;

用struct定义的类里面的成员变量默认都是public类型的,也就是可以在类外访问的,但是class定义的默认都是private类型的,它是私有成员变量,不允许在类外访问的,但是如果改成public就变成可以在类外访问的了;
在这里插入图片描述

对象在内存中的存储方式

对象在类中是如何进行存储的?对于每个类类型对象的成员变量和成员方法每个都要进行存储吗?

首先看成员变量的存储:
在这里插入图片描述

这里可以看到对象在存储成员变量的时候,同样采取内存对齐的方式存储;

那对于成员函数呢?
是不是还是要再开辟额外的空间为成员函数用呢?

其实不然,即使对象不同,其实调用的方法是同一个,只不过对象中的数据在变化;优化一下可以将重复的代码放入代码段,只保存其地址就可以优化很多;

那也就是说只要保存函数的入口地址,将它当作指针来看吗?
相当于Date类中是:
三个int和一个指针

sizeof(Date)应该是16吧
在这里插入图片描述
加入了一个函数,对象的大小并没有变化。

所以正确的存储方式是只保存了成员变量;

但是类同样是有区别的,存在空类;
难道空类创建的对象大小就是0吗?因为没有成员变量啊

但是,空类的大小是1;
在这里插入图片描述
这里A虽然是个空类,但是它有大小!

因为如果空类类型的对象大小是0,其创建的对象就没有了区别,无法做到区分;
我们都知道在函数中创建的局部变量是创建在栈上的,并且根据大小向高地址拓展,包括main函数中的变量,如果我们将空类类型对象的大小设置为0,那a1和a2的地址不就重合了吗,但是我们仔细看监视窗口发现,a1和a2它们的地址并不相同;
在这里插入图片描述
换句话说如果地址相同了,怎么做到区分呢。。。

this指针

重新回到上面的日期类问题,
在这里插入图片描述

这里为什么通过不同的对象调用相同的成员函数还能不出错呢?成员方法是怎么知道谁调用的它呢,成员函数的参数里面明明只有三个int类型参数,并没有指明是哪个对象。

但其实成员函数是有隐藏参数的,这个参数就是 this指针
在这里插入图片描述
为什么打印出来的这个this指针和d1,d2,d3的地址完全相同呢,而且在这个函数中并没有显式定义这个this指针,反倒可以打印出这个this指针,证明这个this指针是编译器自动生成的而且是默认传参的;

this指针的值和调用成员函数的对象地址相同,目的就是让成员函数知道是谁在调用它;

那this指针是和调用成员函数的对象地址相同,我可以不可以修改它的指向,让它指向另一个指向从而修改另一个对象的内容呢?

很显然是不可以的,this指针的类型是类类型 * const this;

这里稍作解释:
const int* p:表示p的指向可以改变,p指向空间中的内容不可以被改变;
int* const p:表示p的指向不可以被改变,p指向空间中的内容可以改变;

所以可以知道,this指针的指向是不可以改变的;并不是一个可修改的左值;而且在非必要情况下,没必要用this->成员变量;

必要情况:函数参数和成员变量重名了

在这里插入图片描述
那么this指针究竟通过什么方式传参呢?这么隐蔽的传参方式

看看反汇编:
在这里插入图片描述
这里可以看见在该函数调用约定_thiscall 下:函数参数是从右往左传参的
所以第一个参数是21,第二个参数是10,第三个参数是2023,第四个参数和前三个参数入栈方式都不一样,前三个参数都是mov进行参数压栈的,但是[d1](表示d1的地址),是通过rcx寄存器传递压栈的;

那么this指针可以为空吗?
可以为空,
在这里插入图片描述
这里在pd=nullptr之后,很明显d1的地址和this指针都为0了,是合法的;
但是不能在this指针为nullptr之后继续访问它的成员变量,对一个空指针继续访问,是访问未分配的地址,是内存访问出错;(nullptr->year这种变量没意义)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值