1.类
1.1定位:
和namespace一样,类也有类域。同样起到既保护又限制的功能。别人不能随意访问类里的东西,得通过特定的方式来访问(访问方法和命名空间域一样,三种方法)。
1.2作用
在C语言中,struct代表结构体,用来放一些结构的基本参数(顺序表:数组、有效数据个数、容量大小;链表:数据域、指针域)。但是在C++中,struct得到了加强,升级版的名字叫class(类)/struct(类),里面不仅能够放基本参数,也能放一些基本函数。(为了区分C和C++,C++一般用class,不过用struct也是可以的。)
#include <iostream>
using namespace std;
//C语言
struct Stack {
int* a;
int size;
int capacity;
};
//C++
//两者在C++都一样,但是为了与C的struct区别,C++用class
//struct Stack{ }; calss Stack{ };
class Stack
{
//以下内容,都叫类的成员
//类的成员函数
void Init(int n = 4) {
a = (int*)malloc(sizeof(int) * n);
top = 0;
capacity = n;
}
void Push() {
//...
}
//类的成员变量
int* a;
int capacity;
int top;
};
1.3定义:
class为定义类的关键字,Stack为类的名字,{}中为类的主体,注意类定义结束时后⾯分号不能省略。类体中内容称为类的成员:类中的变量称为类的属性或成员变量;类中的函数称为类的⽅法或 者成员函数。
1.4与C中struct的区别
第一点:class能在里面定义或者声明函数。C中struct不行。
第二点:class中类的名字能代表类型。C不行,类型表示必须类型+名字。(C中匿名结构体就不说了,使用的情况太少了)
// C 类型+名字=变量
struct Stack st;
//C中匿名结构体
strucr st;
// C++ 名字=变量
Stack st;
第三点:class成员变量同样要内存对齐,这点和C一致。内存对齐是为了方便硬件读取数据。(这里就是我们今天要了解的第二大点 ‘ 类的实例化 ’ )
第四点:class有访问限定符。C语言没有。
访问限定符是什么,通俗的说,对于一块儿空间,对它的访问限制更强。有些外面能指定就能访问;有些即是指定,也无法访问。
访问限定符有三种
public:成员在类外可以直接被访问 |
protected:成员在类外不能直接被访问(在继承中才能与private区别开) |
private:成员在类外不能直接被访问 |
注:class定义成员没有被访问限定符修饰时默认为private,struct默认为public。
在C++中,我们可以对特定成员加上访问限定符。这就有一个问题,访问限定符的作用范围是从哪到哪?
作用范围:访问权限作⽤域从该访问限定符出现的位置开始直到下⼀个访问限定符出现时为⽌,如果后⾯没有 访问限定符,作⽤域就到}即类结束。
2.类的实例化(对象)
1.1概念:
就是类的定义。类就像设计图,类的实例化是根据设计图造实物。
想清楚什么叫 ‘ 定义 ’ 。定义就是在内存中开空间。如果没有开空间,就是没定义。
1.2内存对齐:
在类的1.4中第三点,我们简单了解到内存对齐。这里在详细说一下内存对齐的规则:
- 第⼀个成员在与结构体偏移量为0的地址处。
- 其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。
- 对⻬数=编译器默认的⼀个对⻬数与该成员⼤⼩的较⼩值。(VS默认为8)(如何修改VS默认值?)
- 结构体总⼤⼩为:最⼤对⻬数( min{所有变量类型最⼤者,默认对⻬参数} )的整数倍。
- 如果嵌套了结构体的情况,嵌套的结构体对⻬到⾃⼰的最⼤对⻬数的整数倍处,结构体的整体⼤⼩ 就是所有最⼤对⻬数(含嵌套结构体的对⻬数)的整数倍。
思考:为什么要内存对齐?
因为计算机硬件设计是32根数据线。也就是说,计算机每次读一次数据,都是4B 4B 的读。如果一个是char类型,一个是int类型。第一次读char的一个字节+int的前三个字节。第二次读int的最后一个字节+剩下的三个字节,就会发生越界访问,会出现随机值。为了避免此情况,所以要设置内存对齐。
1.3类的所有成员,都需要实例化么?
我们在上面的图片可以看到。在sizeof(st)时,输出是16。但是新问题是,为什么只有16?成员函数如果不算,那么16好解释。然而事实是什么?
事实就是如此,在计算类的大小时,只计算成员变量(这点和C的struct一样),成员函数不计算。
那么成员函数的空间,定义在哪了?现在我也不不太明白。只知道成员函数在公共代码段。仔细想一下,如果类实例化很多次,虽然成员变量可能不一样,但是成员函数肯定一样啊。如果成员函数也是跟着再开空间,那空间就会浪费太多。
1.4类的实例化,最小为多少?
因为如果⼀个字节都不给,怎么表⽰对象存在过呢?所以这⾥给1字节,纯粹是为了占位标识 对象存在。
3.this指针
3.1作用:
分清哪个对象在调用成员函数
d1和d2都调用Print,那么为什么结果不一致呢?
这就是this指针的作用了:编译器编译后,类的成员函数默认都会在形参第⼀个位置,增加⼀个当前类 类型的指针,叫做this 指针。⽐如Date类的Init的真实原型为, void Init(Date* const this, int year, int month)
注:为了区别成员变量,习惯上成员变量会加⼀个特殊标识
3.2定义:
类的成员函数中访问成员变量,本质都是通过this指针访问的,如Init函数中给_year赋值, this->_year = year;
注:this指针,只指向成员变量,不指向成员函数。
3.3使用
C++规定不能在实参和形参的位置显⽰的写this指针(编译时编译器会处理),但是可以在函数体内显 ⽰使⽤this指针。