“我知道攀登高峰的崎岖变得越难越难走”
————————《西门少年》
在C++的学习中,掌握类和对象,是打开Cpp学习的敲门砖。
(1)类的引入:
①struct:
我们知道,在C中可以用结构体 struct 定义一个多种类型的集合:
strcut A
{
int a;
char* pa;
double b;
};
那么在C++中我们也继承了C的传统,另外在struct中,除了定义变量,还可以定义函数。
struct A
{
//定义的函数
int Add(int a, int b)
{
return a + b;
}
void PrintA()
{
cout << "PrintA()" << endl;
}
//变量声明
char _a[10];
int _b;
int _c;
};
因为这里为了区别,c++中 更喜欢用class 来 替代struct。
②class:
形如struct,class 和struct类似.
class B//类名
{
//成员函数 或者 类的方法
void PrintB()
{
cout << "PrintB()" << endl;
}
//成员变量
int _a;
char* pc;
};
根据上图,可以确定一个 类的元素是由,成员变量、成员函数构成。
(2)类的定义:
在上面代码的展示里面,都是类定义的一种。其实类定义分为两种。
1.声明和定义全部放在类体中,需要注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。
2.声明放在.h文件中,类的定义放在.cpp文件中
不过在类外定义函数的时候,要用"::" 指定类域。类域左边是返回值,右边是函数名。
(3)类的访问以及权限:
C++相对于 C 更加安全就在于,在C++的类引入了限定符。
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
①pubilc:就是公共区域,类外类内都可以调用。
②proted和private在现在,我们统一都理解为一个意思。类外不能直接访问。
(一)struct 与 class 默认权限的区别:
此时我们可以对struct内部进行访问。
然而,当我们用class 的时候,则不会让类外成员直接访问。
所以我们总结:
class的默认访问权限为private,struct为public。
所以,让类外 访问进class里的内部,也就只需要 改变就行。
(4)类的作用域以及类的大小:
在类的定义中,引入了类域的概念。
在类体外定义成员,需要使用 :: 作用域解析符 指明成员属于哪个类域。
class Person
{
public:
void PeopleInfore();
private:
char _name[10];
int _age;
char _sexy[5];
int number;
};
//声明类域
void Person::PeopleInfore()
{
cout << _name << _age << number;
}
类的大小:
那么,如果类里没有变量成员,大小又该是多少呢?!
可以看出,当类为空空类时,仍然占有一字节。此时的一字节不是具体内存大小。而是作为占位存在。
类里的成员函数是否也占有大小呢?那成员函数存储在什么区域?
答案是,类大小的计算不包含成员函数。
因为,每个类 调用的都是同样一个成员函数,但是有不同的成员变量。所以,如果每次创建一个类,就要为成员函数开辟空间,造成空间浪费。因为仅仅需要一份就够了。
一个类,只保存成员变量,成员函数存放在公共的代码段。
所以计算类的大小,和C中计算结构体大小一样。
内存对齐规则:
1. 第一个成员在与结构体偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是 所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
(5)this 指针:
在C++中,this指针是一个很重要的概念。
我们先写一个Date(日期) 类;
class Date
{
public:
void InitDate(int year,int month,int day)
{
_year = year;
_month = month;
_day = day;
}
void Display()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
d1.InitDate(2022, 6, 21);
d1.Display();
Date d2;
d2.InitDate(2018, 6, 7);
d2.Display();
return 0;
}
很清楚的知道,在类外定义了两个d1 和 d2。他们两个都分别调用同一个成员函数InitDate 和 Display。
但为什么,该函数能分别对d1,d2分别设置呢?!
C++中通过引入this指针解决该问题。
什么是this指针?
this指针,是一个隐藏的指针参数,目的是为了让该指针当前运行的对象,去进行函数的调用和参数的应用。
所以我们也可以这样用:
在每个操作代码前,添加this指针。
那么我们是否可以把这个this指针,在函数参数一栏补充出来呢?
当然是不行的。因为这是编译器自己补充,并不是让用户知晓。
this指针的特性:
1. this指针的类型:类类型* const。
2. 只能在“成员函数”的内部使用。
3. this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this 形参。所以对象中不存储this指针。
4. this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。
两个问题:
1. this指针存在哪里? 2. this指针可以为空吗?
1.根据上面特性,第一个问题很简单,this指针是形参,是在调用函数的时候形成的临时拷贝。所以是在保存在栈上。
2.可以看出这个哈拿书可以正常运行
但运行第一个函数 直接跑死掉。
传过去的this 接收到的是nullptr的空指针,并对空指针, 解引用。所以导致程序崩溃。
别走哦~ 还有下