3.抽象与面向对象的三大特性---封装
在了解面向对象之前,首先要理解抽象的概念
1.抽象
抽象就是提炼具体事物的共同特性(或者说集合),再把这些共同特性归纳为类,这个过程就是抽象
类:特性的集合
对象:具体的事物
例如:
从我们程序员的角度来说,我们每天都会在三个世界遨游,分别是现实世界、思维世界、数字世界
现实世界就是物质世界,也就是我们一直生活的世界
思维世界就是程序员脑海中的各种想法,在脑海中构建出一个世界,比如一说到摩托车,脑海中就有画面了,但具体什么是摩托车还说不上来
数字世界就是电脑的世界,用代码创造的世界
抽象就是"现实世界->思维世界->数字世界"的这个过程
现实世界的各种事与物,通过在思维世界归纳为类,最后在数字世界变为函数和数据,这个过程就是抽象
| 现实世界 | 思维世界 | 数字世界 |
| 摩托车 | 类(两个轮子,会跑),对象(摩托车) | 数据(两个轮子),函数(跑) |
| 杯子 | 类(圆柱,能装水,装500ml水),对象(杯子) | 数据(圆柱(形状),容量(500ml)),函数(装水) |
由抽象就可以得出一个结论,就是万物皆对象
面向对象的语言有很多种,但总的来说,就是概括的三大特征:封装、继承、多态
补充一个知识点:
语法:
每种编程语言都有独属于自己的语法,而且语法超级多,不可能每个语法都记得住,每种语法也不一定都用得到,所以说只要掌握常用的语法
其实就能编程了,就算不知道某一个语法,也不会影响到开发
语法只是用来忽悠编译器的,只要做出来的过程是自己所想的就行
程序员锻炼的是解决问题的方式,并不是一个翻译
2.面向对象三大特征---封装
封装就是为了代码的安全而诞生的
举例来说,一个银行账户,你在里面存了很多钱,你肯定不希望这笔钱其他人都可以随意取出来花掉,那么你可以给银行账户设置一个密码
这样其他人即使知道了你的银行账户,不知道密码,也无法把钱取出来。设置密码就是封装
类似的,我定义了一个对象,肯定不希望里面的东西其他人能随意修改,那么我就只把可以修改的公开,不想被修改的不公开,这就是封装
封装就是三个修饰词:private(私有的),public(公有的),protected(受保护的)
这章只说private和public,protected后面会说到
private:被修饰的成员(变量、函数)不能通过对象名访问,只能成员函数访问
public:被修饰的成员(变量、函数)可以通过对象名访问,也可以通过成员函数访问
类封装的本质,就是限制不能用对象名去访问,但其实就在那里(可无视之)
3.面向对象引申出的问题
类与对象有什么区别?
类占据的是代码段,对象占据的是内存段(栈、堆)
一个对象的大小是由什么组成的,为什么?
对象的大小就是类中所有成员变量的大小的和
对象的大小不包括成员函数,因为函数与类名是放在代码区的,在代码区每一个函数都会有一个地址
最后能通过对象默认绑定的this指针+函数名,就能访问到对应的函数
代码区是只读的,并且在程序运行的前一刻就确定了,程序运行后无法改变
为什么对象名可以访问成员函数,或者说为什么对象名+函数名可以访问成员函数?
对象名就是偏移量,再加上函数名(函数地址),就能够找到对应的函数
为什么对象名+成员函数可以访问栈区里的内存段?
通过对象名默认绑定的this指针,访问对象名绑定的内存段
补充:类的大小会自动对齐
前面说了类的封装其实可以无视之,因为可以使用指针规避封装
所以说面向对象的本质就是面向过程,使用内存去实现,我们只需要关心数据,和如何操作数据的流程就行了
举个例子:
class Ribbit { privete: string breed; string name; string six; int wight; } Ribbit r1; int* p = (int*)&r1; //地址本质上就是一个整数 p += 21; //sizeof(Ribbit) = 88 , 88 / 4 = 22 ,22 - 1 = 21(地址是从0开始算的,所以要减1) *p = 666;
4.面向对象的构造与析构
构造与析构,分别对应对象的出生于死亡
构造器(构造函数):对象的出生
1.构造出对象,分配资源
2.构造函数名字和类名相同
3.构造函数没有返回类型
4.一个对象有且只有一个构造函数,必然在构造对象同时被调用
析构器(析构函数):对象的死亡
1.析构对象,释放资源
2.析构函数是类名前加~
3.析构函数必然在对象呗释放的时候调用一次
4.析构函数没有参数,所以也无法重载
class Ribbit { public: Ribbit(); //默认构造函数 Ribbit(string breed,string name,string six,int wight); //重载构造函数,可重载多个
~Ribbit(); //默认析构函数 privete: string breed; string name; string six; int wight; }
5.类的常量成员
关键字(修饰符):const
被const修饰的变量必须初始化,而类中定义一个变量时,无法初始化
想要初始化,就要用到自动传参列表
const也可以修饰函数
class Ribbit { public: Ribbit(int wight,int age):wight(wight),age(age){}; //自动传参列表 privete: cosnt int wight; const int age; //放在返回值前面,用来修饰返回值,表示返回值是一个常量 const int show(int age); //放在函数名前,与放在返回值前等同 int const show(int age); //放在函数名后,用来修饰成员变量,表示该函数中的成员变量的值无法被修改 int show(int age) const; //放在参数列表中,用来修饰形参,表示该形参无法被修改 int show(const int age); }
浙公网安备 33010602011771号