目录
类的实例化
用类类型创建对象的过程,称为类的实例化
- 类只是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它
- 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量
- 做个比方。类实例化出对象就像现实中使用建筑设计图建造出房子,类就像是设计图,只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间
计算类的大小
计算类的大小,我们可能想到是不是和C语言中计算struct的大小方法是一样的。
但是,问题是class中包括了struct中成员函数。
我们发现并没有计算函数的大小,实际上我也还从听说过函数有大小。
实际情况如下:
一个类的大小中只保存成员变量,成员函数存放在公共代码区
其实可以理解,方法是同类对象公用的,但是属性是各有不同。
我们再看一个特例:
结论:一个类的大小,实际就是该类中”成员变量”之和,当然也要进行内存对齐,注意空类的大小,空类比
较特殊,编译器给了空类一个字节来唯一标识这个类。
下面附上结构体内存对齐规则:
- 第一个成员在与结构体偏移量为0的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
VS中默认的对齐数为8 - 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
- 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
this指针
引入
有了对上面的类的计算的了解后,这个this指针就多一层理解(为什么方法能够是对象们共用的)。
这个this指针也只出现在成员函数中。
我们首先引入一个问题:
#include <iostream>
using namespace std;
class Person
{
public:
void func(int age)
{
age = age; // 注意之处
}
private:
int age;
};
int main()
{
Person p1;
p1.func(3);
return 0;
}
这个func()
的功能就是给对象赋值,但是上面的代码逻辑上是错误的。
age = age;
我们希望前面的age
是对象属性,其实是参数age
。
我们除了可以通过修改形参(成员变量)名称解决问题外,还可以通过this
指针来处理。
void func(int age)
{
this->age = age;
}
谁调用这个函数,我们就可以认为this
指向了谁。
有了上面这个结论,我们就能明白,为什么函数可以是共有的。怎么区分是哪个对象在使用函数。就是通过this
指针。
C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
#include <iostream>
using namespace std;
class Person
{
public:
void func(int age)
{
this->_age = age;
}
void show([Person* this]) // [] 中的内容是代码中实际不存在的
{
[this->]_age = age; // 注意之处
}
private:
int _age; // 属性换了个名称
};
int main()
{
Person p1, p2;
p1.func(3);
p2.func(6);
p1.show();
p2.show(); // 注意之处
return 0;
}
特性
1.this
指针的类型:类类型* const
2. 只能在“成员函数”的内部使用
3. this
指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this
形参。所以对象中不存储this
指针。
5. this
指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx
寄存器自动传递,不需要用户传递