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);
}

 

posted @ 2020-05-07 20:57  打好基础才是第一步  阅读(298)  评论(0)    收藏  举报