目录
1.面向过程与面向对象的区别
什么是面向过程?
即关注过程,以过程为主,比如之前用C语言写过的井字棋小游戏,整体为“我下棋、判断胜负(同时判断棋盘是否已满)、电脑下棋、判断胜负(同时判断棋盘是否已满)”这样由过程的循环这样组成的程序。
总而言之,面向过程:更关注过程,将分体的解法拆分成各个过程,用函数完成单个或多个过程,通过函数调用解决问题,而C语言就是面向过程的语言
我们以洗衣服为例子:
C语言通过将每个过程写成单个函数,通过将这些函数封装在一个大函数中来实现一个名为“洗衣服”的函数
什么是面向对象?
顾名思义,即关注的是对象,将一件事中参与的所有对象拆分开来,依靠对象之间的相互交互完成。
面向对象:关注对象,将事情拆解成不同对象,以对象之间的交互完成事情
仍以洗衣服为例子:一个人将衣服放入洗衣机中洗,这里会拆解成三个对象:洗衣机(内置洗衣粉和水)、人、衣服
整个洗衣服的过程为:人把衣服放入洗衣机中,启动洗衣机后洗衣机根据选择的洗衣模式自行加水使用洗衣粉(液)洗衣服,洗衣机完成洗衣、甩干后,人再将衣服晾到其他地方上。
整个过程中,人并不知道洗衣机的整个工作过程,也不关心洗衣机的运行逻辑,只需知道洗衣机能使衣服变干净。
C++就是面向对象语言,更加关注参与的对象
2.类
根具上面对对象的描述,对象和C语言中的结构体很像。C++中,结构体升级成了类,C语言中的结构体只能定义变量,而C++中的类还可以定义函数。
而C++兼容C语言,因此C语言中的结构体关键字“struct”在C++中也算为类,可以定义函数
struct Stack { //初始化函数 void Init(int capacity = 4) { _a = (DataType*)malloc(sizeof(DataType) * capacity); //判断是否开辟成功 if (_a == nullptr) { perror("malloc err:"); return; } _capacity = capacity; _size = 0; } DataType* _a; int _size; int _capacity; };
而C++中,常用关键字“class”来定义类
//A:类名 class A { // 成员函数、成员变量 int a; int b; };
class是定义类的关键字。A是类名(我们自己起的)。{}内是类的主体,可以有变量,也可以有函数。注意类定义结束时一定不能省略分号“;”
2.1类的定义
类的两种定义方式:
1、声明定义全放于类体内
声明和定义全部放在类体中。需注意在类中定义的成员函数默认都是用inline修饰的。至于编译器是否让它成为inline函数,取决于编译器本身
//定义一个时间日期类 class Data { void Print() { cout << _year <<" - "; cout << _month << " - "; cout << _day << endl; } int _year; //年 int _month; //月 int _day; //日 };
2、声明和定义分离
类声明放在.h文件中,成员函数定义在.cpp文件中。
注意:成员函数名前需要加类名和作用域限定符(类名::函数名)。否则编译器无法确认该函数是属于那个类中的
Data.h 中
class Date { public: //声明 void Print(); int year; int month; int day; };
Data.cpp 中
#include"Date.h" void Date::Print() { cout<<year<<endl; }
注意:
声明和定义分离的成员函数默认不是inline修饰的!
2.2类的访问限定符
访问限定符
可以看到上面写的代码中,在class里有一句“public”,这个就是访问限定符。
访问限定符顾名思义,用于限制类成员变量被访问。
若没有访问限定符,我们就能直接访问类成员甚至修改类成员。
访问限定符的主要作用在于保护部分类成员。
访问限定符分三类:
public (公有):
用public 修饰,类中从public开始直到遇到下一个访问限定符为止之间的内容,类外面和类里面都可以访问,若没有下一个访问限定符。类中从public位置开始直到类域结束之间类体中的内容即可以通过外部进行访问,也可以通过内部进行访问,因为是公有的。
protected(保护)和private(私有):
此处protected和pirvate是类似的,protected和private修饰的成员在类外不能直接被访问。从protected 或 private 位置开始,直到遇到下一个访问限定符为止,两者之间的成员不能在类外面直接访问。
说明:
1、public 修饰的成员在类外可以直接被访问
2、protected 和 private 修饰的成员在类外不能直接被访问(此处protected和private是类似的)
3、访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现为止
4、如果后面没有访问限定符,作用域就到 } 即类结束。
5、class的默认访问权限private,struct默认为public(因为struct要兼容C的结构体用法)
注意:
访问限定符只在编译时有用,当数据映射到内存后,没有访问限定符上的区别!
3.类的作用域
类域:
类定义了一个新的作用域,叫类域。类域与命名空间域、局部域、全局域类似。
类中的所有成员都在类作用域中。在类体外定义成员时,要加上作用域限定符,通过::作用域限定符指明成员属于那个类域
#include <iostream> using namespace std; //日期类 class Date { public: void Init(int year = 2023, int month = 4, int day = 29) { _year = year; _month = month; _day = day; } //打印函数声明 void Print(); int _year; int _month; int _day; }; //类内部函数的定义 void Date::Print() { cout << _year <<" - "; cout << _month << " - "; cout << _day << endl; } int main() { Date st1; st1.Init(); st1.Print(); return 0; }
与命名空间域一样,想要访问类域中的成员需要加上“::”访问符。
4.this指针
以上面的代码为例,我们在调用变量st1内部的函数Init和Print时,均未写参数。
C语言中像链表这样的数据结构,在调用类似增删查改这样的函数时,需要传链表变量地址的参数,因为需要告诉函数是哪个变量需要调用此函数。
1、C++编译器给每个非静态的成员函数,增加了一个隐藏的指针参数,让该指针指向当前对象(调用该函数的对象)。
在函数体中所有对成员变量的操作都是通过该指针去访问,且参数是编译器自动传递的,不需要用户来传递,该参数指针起名为this
2、使用范围:
this指针只能在成员函数的内部使用,出了函数作用域形参会被销毁了,在成员函数内部可以通过显式的书写this指针进行访问成员变量。也可以默认用隐式的访问。而this指针本身是不能在函数内部修改的因为是用const修饰的。
3、存储本质:
this指针本质上是函数的形参,只不过是隐式传递的参数(编译器自动传递)当对象调用成员函数时,将对象的地址隐式的传给this形参。所以this指针不在对象中,而是存储在栈区中。
4、传递方式:
this指针是成员函数,第一个隐含的指针形参,一般情况下都是由编译器自动传递的(编译器通过ecx寄存器自动传递),不需要用户自己传
在编译器眼中,类内部的函数都是下面的样子,但由于this指针的隐式的,因此我们不能在定义函数时写上去。
总结:
对象在调用成员函数的时候,编译器会自动将对象的地址传给this指针,用户不可在进行显式传对象地址。在成员函数内部可以显式的通过this指针去访问成员变量,this指针默认是用const修饰的不可在成员函数内部修改this指针的值。this指针本质是一个存储于栈区的形参。