【C++】类的引入及其意义

前言


  • 🚄 输入是学习的本质,输出是学习的手段。
  • 🔖 分享每一次的学习,期待你我都有收获。
  • 🎇 欢迎🔎关注👍点赞⭐️收藏✉评论,共同进步!
  • 🌊 “要足够优秀,才能接住上天给的惊喜和机会”
  • 💬 博主水平有限,如若有误,请多指正,万分感谢!

☁️类的引入

在C语言中,我们学习了struct,但是*C语言中的struct只能定义变量,无法定义函数。

C++中也可以使用struct,且C++中的struct是兼容C语言的struct,并对其延伸——在C++中,struct可以定义函数

struct student
{
	void Print()
	{
		cout << "name:" << _name << endl; 
        cout << "num:" << _num << endl; 
        cout << "age:" << _age << endl;
	}


	
	char _name[20];
	int _num;
	int _age;

};

C++中,更喜欢用class来代替struct,称为类。

所谓的类封装,就好比DNF、剑网三中的一个个人物一般,他们都是被封装起来的,我们作为玩家、用户
官方当然不允许玩家拥有随意更改人物属性的权利,否则不就人人都是一刀99999,这样游戏的寿命顷刻间就会被消耗殆尽,我们只能进行一些官方允许我们进行的操作。

比如放技能,走路…而这些都可以理解为其本质是在使用类成员函数。


C++中,class与struct有何区别?

C++中,class与struct在功能上基本相同,class既能定义变量,也能定义函数,struct也是如此。

它们唯一的区别在于:class的默认访问权限为private,struct的默认访问权限为public.根据使用场景不同,有时需要选择性地去使用。但总的来说,class的默认权限有利于更好地体现封装性,因而更常使用。


☁️类的实例化

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

类是一个抽象的定义,只是一个像模型一样的东西,限定了有哪些成员,定义本身不会分配实际的内存空间。

就像一个房子的设计图,画的设计图本身不会占据实际的地理空间。我们通过图纸建造出来的房屋,

才会占用实际的空间。类的实例化就好比用设计图实际建造出来的房屋,具有实际的空间。

类的定义不会分配实际的内存空间,类的实例化才会分配到实际的内存空间


☁️类对象的大小

在C语言中,我们学会通过内存对齐的原则去计算结构体的大小,类对象的大小,也是通过内存对齐计算大小的。

而计算大小的前提是我们知道类对象中有哪些成员。

我们看这样一段代码


class Student
{
	void Print()
	{
		cout << "name:" << _name << endl;
		cout << "num:" << _num << endl;
		cout << "age:" << _age << endl;
	}



	char _name[20];
	int _num;
	int _age;

};


int main()
{
	Student st;
	int sz = sizeof(st);
	cout << "sz = " << sz << endl;

	return 0;
}

如果我们先不看成员函数,依据内存对齐的方式计算类对象的大小,会算出 sz =28。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CUkTfUjO-1646459208440)(C:\Users\Z-zp\AppData\Roaming\Typora\typora-user-images\image-20220129185520491.png)]

运行结果与我们计算的一致,说明我们的假设成立,编译器是否也和我们一样,

不把成员函数当做类对象的一部分

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sShC3B1o-1646459208441)(C:\Users\Z-zp\AppData\Roaming\Typora\typora-user-images\image-20220129190445897.png)]

有这么两个类对象,很显然,它们的成员变量并不相同,但是当他们调用Print函数的时候,函数的定义是一模一样的

如果每个对象都将这样的函数纳入对象本身,则一个对象需要额外分配一个空间给Print函数,如果有100个、

1000个对象呢?那么我们是不是还要额外分配这么多个空间给Print函数,但是每个Print函数的定义都是一样的,

这就造成了一种不必要的浪费,如果我们将成员函数保存在一个公共代码区中,

无论你有多少个这样的对象,你需要调用成员函数,就拿着这个函数的地址来这里调用,而函数也就写这一个,不会造成无意义的重复。

因此,类对象中只包含成员变量,不包含成员函数

分析一下这段代码的运行结果

// 类中既有成员变量,又有成员函数
class A1 {
public:
	void f1() {}
private:
	int _a;
};
// 类中仅有成员函数
class A2 {
public:
	void f2() {}
};


// 类中什么都没有---空类
class A3
{};

int main()
{
	A1 a1;
	A2 a2;
	A3 a3;

	int sz_a1 = sizeof(a1);
	int sz_a2= sizeof(a2);
	int sz_a3 = sizeof(a3);

	cout << "sz_a1 = " << sz_a1 << endl;
	cout << "sz_a2 = " << sz_a2 << endl;
	cout << "sz_a3 = " << sz_a3 << endl;

	return 0;
}
  • a1的大小是4。

既然对象中不包含成员函数,那么a2和a3的大小就应该是一样的,先看看运行结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S6NgwL6N-1646459208441)(C:\Users\Z-zp\AppData\Roaming\Typora\typora-user-images\image-20220129192323081.png)]

既然对象里什么都没有,为什么计算出来会有一个字节?

先来思考这样一个问题:如果我这样定义对象

//注意:A3是空类

A3 t1;
A3 t2;

那编译器凭什么区分t1和t2,知道这是两个对象,而不是同一个对象?他们都是空类的对象,对象中都没有成员变量。但是,在内存中,不同的对象它们的地址肯定是不同的,给4个字节的地址用来区分两个空对象,显然有点得不偿失,因此编译器给了1个字节给空对象,用来占位表示它们在这里存在过,借此对它们进行区分。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿波呲der

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值