类与对象 一

从面向过程到面向对象

一,结构体和类

在c语言中,结构体是我们学过且的自定义类型,它是由多种基本数据类型组合而成的,其实他与我们即将要学习的c++中的类有密不可分的关系。下面我们对比学习一下。

struct A
{
	int a;
	double b;
	char c;
};
class B
{
	int a;
	double b;
	char c;
};

上面的结构体A和类B是不是非常的相似,只是存在关键字classstruct的差别,虽然只是一字之差,但区别却千差万别。
在C语言里面,结构体里面只能定义变量,因为C++兼容C语言,在C++中,结构体与类一样,不仅可以定义变量,还可以定义函数

struct A
{
	// 默认属性为public
	int a;
	double b;
	char c;
	void a(){};
};
class B
{
	// 默认属性为private
	int a;
	double b;
	char c;
	void b(){};
};

但是重点来了,C++中结构体与类的区别

结构体(struct)中默认访问为public
类(class)中默认访问为private
(未完,后续继承和模板还有区别)

这个不理解没关系,后面会逐步解疑

二,类的定义

  1. 书写形式
class ClassName 
{
	// 类体:成员变量 和 成员函数
};

在类里面,变量都称为成员变量,函数都称为成员方法/函数。
class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。

  1. 两种定义形式:

类内定义:
类外定义:在这里插入图片描述
需要注意的是:类内定义的函数编译器当成内联函数处理

三,访问限定符

C++的类中有三种访问限定符:

访问限定符
public 公有
private 私有
protect 保护
  1. public

权限最大,public修饰的成员在类外可以直接被访问

  1. private

权限最小,public修饰的成员只能在类内被访问

  1. proctect

本类和继承的子类可以访问

四,类的对象模型

类,就像一张工程图纸,里面记录满了整个工程实现的细节;而对象就像按照工程图纸实现出来的实物,如按照图纸造汽车,建大楼。

1.空类的大小

  1. 类没有分配实际的内存空间,只是一个模型一样的东西。
  2. 但是对于一个空的类,他的大小却是1字节。这是为什么呢?

答:

C语言中,结构体不能为空;C++中结构体和类可以为空,但是大小不为0,而是1,这是因为空类和结构体可以实例化,既然可以实例化,那么它就可以被使用,如果内存没有分配大小给他们,那么如何使用他们呢,所以规定空类和结构体的大小为1字节,用来存储地址

实例代码:

class A {};
struct B {};
int main()
{
	A a;
	B b;
	cout << "空类A的大小:" << sizeof(A) << endl;
	cout << "空结构体B的大小:" << sizeof(B) << endl;
	return 0;
}

a,b大小都为1字节,用来存储地址

2. 类对象存储方式

我们知道,类是由成员变量和成员函数构成的,那他们在内存中的存储方式是怎么样的,是和结构体一样吗?根据内存对齐1来划分大小,那成员函数的大小又该如何分配呢?下面我们来逐一分析。

class A 
{
	char a;
	int b;
	double c;
	void func() {};
};
int main()
{
	A a;
	cout << "A的大小:" << sizeof(A) << endl;
	cout << "a的大小:" << sizeof(a) << endl;
	return 0;
}

在这里插入图片描述
可以看到,类A和对象a的大小都是16,我们根据结构体对齐规则1可以算出 4 + 4 + 8 = 16,不难发现,没有把函数的大小算进去,那么是函数没有内存大小吗?显然不是,这里面的原因就涉及到了分区存储。

C++对类信息存储的做了处理,把成员变量和成员函数分开存储2,成员变量分为静态变量和非静态变量,静态变量存储在静态区(数据区),非静态变量存储在当前代码块栈区里的栈帧里面;而成员函数则存储在代码段里面类的大小只计算非静态变量,所以大小为16字节。

这里解释一下,为什么成员函数放在代码段里面,这样做的目的是减少内存存放相同功能的代码而造成的浪费,提高代码利用率,想想一个对象里面成员函数都是一样的,如果每个对象都把成员函数纳入存储范围,是不是就造成了代码重复存储和空间浪费。

五、this指针

先看一段代码,思考一个问题,有一个Date类,我们调用成员函数Display,在有多个对象的时候,各个对象里面的_year变量是如何区分的呢?

class Date
{
public:
	void Display()
	{
	cout << _year << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d;
	d.Display(); // 相当于d.Display(&d); &d是编译器自动传递的
	return 0;
}

答案是这样:
在这里插入图片描述

  1. 对于区别不同对象的数据值,每个成员函数都会有个隐形参数this来接受对象的地址。
  2. this是参数,类型是 类类型 *const,是函数调用时编译器通过ecx寄存器自动传递,不需要用户传递

提问:

  1. this指针存在哪里?
  2. this指针可以为空吗?

答案:

  1. this指针是个形参,存在成员函数的栈帧里。
  2. 可以为空,只要不访问解引用的this,就不会出错,因为成员函数在代码段里,是对象的公共调用区域。
    在这里插入图片描述

  1. 结构体对齐规则 ↩︎ ↩︎

  2. 运行内存分配 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值