目录
一.什么是类
简单来说,C++中的类就是C结构体的升级版。
C++类对比C结构体不仅可以定义成员变量,还可以在里面定义函数。
struct Stack
{ //函数里面用的变量可以直接在结构体中找到
void Init(int n=4)
{
_array = (int*)malloc(sizeof(int ) * n);
if (nullptr == _array)
{
perror("malloc申请空间失败");
return;
}
_capacity = n;
_size = 0;
}
//成员变量
int* _array;//加 _ 为了防止与参数重名
size_t _capacity;
size_t _size;
};
二.类的定义
关于类的定义,我们一般用class关键字来定义。
class className//类的名字
{
// 类体:由成员函数和成员变量组成
}; // 一定要注意后面的分号
1.访问限定符
访问限定符有3个,public(共有) private(私有) protected(保护)。
访问限定符说明
1. public修饰的成员在类外可以直接被访问
2. protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
4. 如果后面没有访问限定符,作用域就到 } 即类结束。
5. class的默认访问权限为private,struct为public(因为struct要兼容C)
class Stack
{
public://共有 可以访问
//函数里面用的变量可以直接在类中找到
void Init(int n=4)
{
_array = (int*)malloc(sizeof(int ) * n);
if (nullptr == _array)
{
perror("malloc申请空间失败");
return;
}
_capacity = n;
_size = 0;
}
int Top()
{
return _size - 1;
}
private://私有 不可访问
//成员变量
int* _array;//加 _ 为了防止与参数重名
size_t _capacity;
size_t _size;
Stack* next;//可以不加class 同样如果用struct 定义类,也可以不加struct
};
int main()
{
Stack s;//创建变量可以不加class 同样如果用struct 定义类,也可以不加struct
s.Init(10);
cout << s.Top() << endl;//访问共有 ok
cout << s._size << endl;//访问私有 no
return 0;
}
2.类声明一般放.h 成员函数定义放.cpp中
注意:在不同文件中定义成员函数名前需要加类名::
//.h
#pragma once
#include<iostream>
using namespace std;
class Stack
{
public:
//成员函数
void Init(int n = 4);
private:
//成员变量
int* _array;
size_t _capacity;
size_t _size;
Stack* next;
};
//.cpp
#include"Test.h"
void Stack::Init(int n = 4)
{
_array = (int*)malloc(sizeof(int) * n);
if (nullptr == _array)
{
perror("malloc申请空间失败");
return;
}
_capacity = n;
_size = 0;
}
3.C++中struct和class的区别是什么?
C++需要兼容C语言,所以C++中struct可以当成结构体使用。另外C++中struct还可以用来
定义类。和class定义类是一样的,区别是struct定义的类默认访问权限是public,class定义的类
默认访问权限是private。
三.类对象模型
1.如何计算类对象的大小
类中既有成员函数又要成员变量,计算的时候要不要把函数当作指针变量来算。
可以看出计算对象的大小只计算 成员变量的大小。
注意:如果是空类(类中没有成员变量)sizeof(空类)==1
用来标识对象被定义出来
2.内存对齐
计算成员变量的大小当然要考虑内存对齐的问题。
1.内存对齐规则
1. 第一个成员在与结构体偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
VS中默认的对齐数为8
3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整
体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
2.为什么进行内存对齐
1.平台原因
不是所有的硬件平台都能访问任意地址上的任意数据的,某些硬件平台只能在某些地址处取某些特定类型的数据。
2.性能原因
计算机在读取内存时,一次只能读64bit 也就是4字节。
如果我们在位置偏移量为1处存放了int a,从位置偏移量0开始,要读2次才可以读完。
3.计算内存偏移量 修改默认对齐数
内存偏移量
offset(结构体名称,成员变量名); 头文件#include<stddef.h>
修改默认对齐数
通过预编译指令来修改
#pragma pack(要修改成为的大小)
四.this指针
1.什么是this指针
我们可以看到 d1.Print() d2.Print(),明明调用的是同一个函数但打印结果是不一样的。
C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
2.this指针的特性
1.this指针类型 (Date*const this)不能改变指向的对象
2.this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给
this形参。所以对象中不存储this指针。3.this指针存储在 栈中,或者ecx(寄存器)。
3.this指针易错点
下面这段代中p明明是空指针,但没有发生运行崩溃是为什么呢?
虽然this和p都是空指针,但PrintA();函数并没有通过this指针访问成员变量,也就不会发生空指针的解引用。
如果访问就会发生运行崩溃。