C++学习笔记(8)——类与对象(中)

系列文章目录


C++学习笔记



前言 C++对C语言缺陷的弥补——封装

C语言结构体中只能定义存放数据的结构,操作数据的方法不能放在结构体中,即数据和操作数据的方式是分离开的,导致面对复杂的过程稍不注意可能就会出错,如:涉及到大量指针操作。

C++中通过类实现了封装。通过封装,我们可以将数据以及操作数据的方法进行有机结合(即方法和数据,相关的放一起,不相关的可以另算,主打一个各取所需😊),通过访问权限限定符可以指定哪些方法在类外可以被调用。

封装后,使用类的过程更符合人类对一件事物的认知。


理解与比喻

封装就像是“一个村庄百余户,家家各扫门前雪,自家种地自家吃,买粮前年商量好,一袋杂粮一家名。”

类的封装,将一堆变量和方法存在一个空间内,在这个空间外无法直接调用空间里面的变量和方法,必须提前规定好哪些变量和方法公开。在空间外使用变量和方法时还要写出对象名才能使用其变量与方法。

类就像是一纸歌词,实例化就是把歌词唱出来可以被听见,不同的人可以唱出不同的旋律。

类像是一种概念模型,它描述了一种类型,说明这个类型有哪些成员,假设了一块还没被分配的内存内存空间来存储它。

一、类的实例化

使用这一类型来创建对象的过程称为类的实例化。类不占内存空间,类实例化的对象占内存空间。

  1. 类像是一种概念模型,它描述了一种类型,说明这个类型有哪些成员,假设了一块还没被分配的内存内存空间来存储它。例如:学生信息表,定义了一种人物类型,但学生信息表本身不是人物;
  2. 一个类可以实例化多个对象,对象会占用实际的内存空间;

打个比方,类起到设计图的作用,类实例化出对象的过程就像是工人根据图纸造出房子的过程。

#include<iostream>
using namespace std;

class Person	//定义一个类
{
public:
   int _age;
   int _num;
   void Printf()
   {
   	cout << _age << "/" << _num << endl;
   }
};

int main()
{
   Person man;	//根据类定义一个对象man
   man._age = 20;	//对man进行自定义操作
   man._num = 10;
   man.Printf();	//使用对象man的方法
   return 0;
}


二、计算类对象的大小

1.对象的存储方式

类中既包含了成员变量又包含了成员函数,当类实例化后,对象保存成员变量,成员函数存放在公共代码区,对象的保存成员函数地址。一个类的大小,实际就是该类中成员变量的大小之和,最终得出的内存大小是内存对齐后的大小。

PS.

  1. 只要有了对象就会分配规定好的空间大小,不论对象的成员变量是否赋值;
  2. 如果对象是空类或对象没有成员变量只有成员函数,则编译器会给予一个占1字节的随机值给对象,起标识作用。
#include<iostream>
using namespace std;

class Person	//定义一个类
{
public:
	int _age;
	int _num;
	void Printf()
	{
		cout << _age << "/" << _num << endl;
	}
};

class Student
{};

class School
{
	void Printf()
	{
		cout << endl;
	}
};

int main()
{
	Person man;
	man._age = 20;
	man._num = 10;
	Student like;
	School daxue;
	cout << sizeof(man) << endl;
	cout << sizeof(like) << endl;
	cout << sizeof(daxue) << endl;
	return 0;
}

计算对象大小案例


2.结构体内存对齐规则

  1. 第一个成员在与结构体偏移量为0的地址处。
  2. 其他成员变量要对齐到对齐数的整数倍的地址处。

PS.
a.对齐数=编译器默认的一个对齐数 与 该成员大小的较小值。
b.VS中默认的对齐数为8

  1. 构体总大小为:最大对齐数的整数倍。(所有变量类型最大者与默认对齐参数取最小)
  2. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

内存对齐的意义是让编译器可以快速读取栈帧内的信息。

#include<iostream>
using namespace std;

class Student	//定义一个类
{
public:
	char _age;
	char _name;
	int _a;
};

class School	//定义一个类
{
public:
	char _age;
	char _name;
};

int main()
{
	Student boy;
	School big;
	cout << sizeof(boy) << endl;
	cout << sizeof(big) << endl;
	return 0;
}

在这里插入图片描述


三、this指针

1、this指针的作用

同一类不同对象使用该类的同一函数时,成员函数是根据this指针来设置不同对象的。

this指针就是一道桥梁,连接对象与函数,当一个对象调用函数时,函数会一对一的为该对象服务。

2、this指针的特性

  1. this指针的类型:“类”类型* const,即成员函数不能给this指针赋值,this指针我们不可更改。
  2. this指针只能在“成员函数”的内部使用
  3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
  4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递
#include<iostream>
using namespace std;

class Person	//定义一个类
{
public:
	int _age;
	void Printf()
	{
		cout << this->_age <<endl;
	}
};

int main()
{
	Person man;
	man._age = 20;
	man.Printf();
	return 0;
}

在这里插入图片描述

this指针存在且积极地起作用。
成员函数内部this指针是存在的,且是积极地起作用


四、面试题——this指针

  1. this指针存在哪里?

this指针存在栈帧里面

  1. this指针可以为空吗?

this指针是可以为空的,只要我们不对它去进行解引用就不会报错。即,this指针可以指向一个空地址,但如果我们解引用该地址则会报错,而我们在没有解引用的前提下去调用公共代码区的成员函数则可以正常使用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值