封装、继承、多态

面向对象的三个基本特征

面向对象的三个基本特征是:封装、继承、多态。其中,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!


封装                                                                

什么是封装?

封装是把数据和过程包围起来,对数据的访问只能通过已定义的界面。在面向对象编程上可理解为:把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类(比如友元类)或者对象操作,对不可信的进行信息隐藏。

封装的实现方式?

1、C++通过自己定义数据类型,比如类,利用类中的访问标识符(public、private和protected),可以实现在类中的封装;通常是将所有的成员变量私有化。

2、将类的定义和实现分离开来

头文件的使用可达到重用的效果;所以将类的定义放在头文件中,而成员函数放在.cpp中定义;而cpp的名字需和类的名字相同。

封装的好处?

封装存在的理由就是重用,重用就是写的一个代码库可以在很多地方重用,而且易于扩充。在一块内存中可以被许多应用程序运用,从开发的角度这样十分的省事,不必做重复的工作,在使用的角度,十分的节约内存,以前一个程序要加载一个库,现在几个程序只需加载一个库就可以了。这就是重用,使用以前的概念是无法实现这个目的的。聪明的程序员解决了这个问题。使用com组件技术,做到了二进制级别的代码重用。相当于扩充了操作系统,因为操作系统就是一个开放的接口,供应用程序调用功能。这就需要二进制级别的封装,而由于一样的c++代码由不同的编译器编译出来的代码不一样,造成了代码之间的兼容问题。因为你封装起来的东西给了使用不同编译器的程序员获得的代码是不一样的,这样就不具备扩充性和灵活性。不能实现代码重用。所以c++语言级别的封装性是十分狭隘的。

继承                                                               

什么是继承?

继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。

通过继承创建的新类称为子类派生类。被继承的类称为基类父类超类。要实现继承,可以通过继承Inheritance)和组合Composition)来实现。在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。

派生类的生成过程:

1.吸收基类成员,但不包含构造函数和析构函数

2.改造基类成员,一是通过继承方式来控制,而是隐藏基类成员变量和成员函数,比如在派生类中声明一个与基类成员同名的成员,这时在派生类中或者在派生类对象中使用该成员名,就只能使用派生类中声明的同名成员。

3.增加新成员。

1派生类对象的执行次序如下:

   1.调用基类构造函数,调用顺序按照他们被继承时声明的顺序(从左到右)

   2.调用内嵌成员对象的构造函数,调用顺序按照他们在类中声明的顺序

 3.调用派生类的构造函数体中的内容

2.派生类析构函数

派生类的析构函数是在该对象消亡之前,做一些清理的工作!析构函数没有类型也没有参数,它的执行顺序和构造函数正好严格相反!

 

继承的实现方式?

继承概念的实现方式有三类:实现继承、接口继承和可视继承

1. 实现继承是指使用基类的属性和方法而无需额外编码的能力;

2. 接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力;

3. 可视继承是指子窗体(类)使用基窗体(类)的外观和实现代码的能力。

1public(公有继承):属于接口继承,继承时保持基类中各成员属性不变,并且基类中private成员被隐藏。派生类的成员只能访问基类中的public/protected成员,而不能访问private成员;派生类的对象只能访问基类中的public成员。

2private(私有继承):属于实现继承,继承时基类中各成员属性均变为private,并且基类中private成员被隐藏。派生类的成员也只能访问基类中的public/protected成员,而不能访问private成员;派生类的对象不能访问基类中的任何的成员。

3protected(保护性继承):属于实现继承,继承时基类中各成员属性均变为protected,并且基类中private成员被隐藏。派生类的成员只能访问基类中的public/protected成员,而不能访问private成员;派生类的对象不能访问基类中的任何的成员。

继承的好处?

     继承可以扩展已存在的代码模块(类),使得代码重用。

多态                                                                

什么是多态?

多态性可以简单地概括为“一个接口,多种方法”,允许将子类类型的指针赋值给父类类型的指针,程序在运行时才决定调用的函数。

多态与非多态的实质区别就是函数地址是早绑定还是晚绑定。如果函数的调用,在编译器编译期间就可以确定函数的调用地址,并生产代码,是静态的,就是说地址是早绑定的。而如果函数调用的地址不能在编译器期间确定,需要在运行时才确定,这就属于晚绑定。

请按顺序写出下面代码的输出结果:

答案:call child func

call ~child

call ~base

多态的实现方式?

C++多态性是通过虚函数来实现的,虚函数允许子类重新定义成员函数,而子类重新定义父类的做法称为覆盖(override),或者称为重写。(这里我觉得要补充,重写的话可以有两种,直接重写成员函数和重写虚函数,只有重写了虚函数的才能算作是体现了C++多态性)而重载则是允许有多个同名的函数,而这些函数的参数列表不同,允许参数个数不同,参数类型不同,或者两者都不同。编译器会根据这些函数的不同列表,将同名的函数的名称做修饰,从而生成一些不同名称的预处理函数,来实现同名函数调用时的重载问题。但这并没有体现多态性。

最常见的用法就是声明基类的指针,利用该指针指向任意一个子类对象,调用相应的虚函数,可以根据指向的子类的不同而实现不同的方法。如果没有使用虚函数的话,即没有利用C++多态性,则利用基类指针调用相应的函数的时候,将总被限制在基类函数本身,而无法调用到子类中被重写过的函数。因为没有多态性,函数调用的地址将是一定的,而固定的地址将始终调用到同一个函数,这就无法实现一个接口,多种方法的目的了。

虚函数的实现机制

虚函数在c++中的实现机制就是用虚表和虚指针,每个类用了一个虚表,每个类的对象用了一个虚指针。要讲虚函数机制,必须讲继承,因为只有继承才有虚函数的动态绑定功能。

c++继承对象实例内存分配介绍:

class A
{public:
    virtual void f();
    virtual void g();
private:
    int a
};

class B : public A
{
public:
    void g();
private:
    int b;
};
//A,B的实现省略
因为A有virtual void f()和g(),所以编译器为A类准备了一个虚表vtableA,内容如下:

 

A::f 的地址

A::g 的地址

B因为继承了A,所以编译器也为B准备了一个虚表vtableB,内容如下:

A::f 的地址

B::g 的地址

注意:因为B::g是重写了的,所以B的虚表的g放的是B::g的入口地址,但是f是从上面的A继承下来的,所以f的地址是A::f的入口地址。然后某处有语句 B b;的时候,编译器分配空间时,除了A的int a,B的成员int b;以外,还分配了一个虚指针vptr,指向B的虚表vtableB,对象b的布局如下:

vptr : 指向B的虚表vtableB

int a: 继承A的成员

int b: B成员


当如下语句的时候:
A *pa = &b;
pa的结构就是A的布局(就是说用pa只能访问的到B对象的前两项,访问不到第三项int b)
那么pa->g()中,编译器知道的是,g是一个声明为virtual的成员函数,而且其入口地址放在表格(无论是vtalbeA表还是vtalbeB表)的第2项,那么编译器编译这条语句的时候就如是转换:call *(pa->vptr)[1](C语言的数组索引从0开始哈~)。
这一项放的是B::g()的入口地址,则就实现了多态。(注意B的vptr指向的是B的虚表vtableB)
另外要注意的是,如上的实现并不是唯一的,C++标准只要求用这种机制实现多态,至于虚指针vptr到底放在一个对象布局的哪里,标准没有要求,每个编译器自己决定。

多态的好处?

多态的目的是为了接口重用。也就是说,不论传递过来的究竟是那个类的对象,函数都能够通过同一个接口调用到适应各自对象的实现方法。

C++支持两种多态性:编译时多态性,运行时多态性。
a、编译时多态性:通过重载函数实现
 b、运行时多态性:通过虚函数实现。

2、虚函数
 虚函数是在基类中被声明为virtual,并在派生类中重新定义的成员函数,可实现成员函数的动态覆盖(Override
3、抽象类
包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能定义抽象类的对象

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值