美文网首页
c++程序员面试宝典之多态与虚函数

c++程序员面试宝典之多态与虚函数

作者: b83dcb2e8b71 | 来源:发表于2018-07-30 10:40 被阅读0次

二十.多态与虚函数

多态:多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态,简单地说是”一个接口多种实现“

C++提供多态的目的:可以通过基类指针对所有派生类(包括直接派生和间接派生)的成员变量和成员函数进行“全方位”的访问,尤其是成员函数。如果没有多态,我们只能访问成员变量。

多态的分类:

1)编译时的多态性。编译时的多态性是通过重载来实现的。

2)运行时的多态性。运行时的多态性是通过虚成员实现的。

下面是构成多态的条件:

1)必须存在继承关系;

2)继承关系中必须有同名的虚函数,并且它们是遮蔽(覆盖)关系。

3)存在基类的指针,通过该指针调用虚函数。

在C++中如何实现多态

答:多态有动态多态,静态多态,函数多态和宏多态等。

  动态多态基于继承机制和虚函数来实现的。

  静态多态引入了泛型的概念。

  函数多态基于函数重载。

  宏多态基于宏替换。

虚函数:

作用:实现多态,基类定义虚函数,子类可以重写该函数,基类指针根据赋给它的不同的子类指针,动态调用属于子类的函数。

底层实现原理:C++中虚函数使用虚函数表和 虚函数表指针实现。通过对象内存中的vptr找到虚函数表vtbl,接着通过vtbl找到对应虚函数的实现区域并进行调用。

什么时候声明虚函数:

首先看成员函数所在的类是否会作为基类,然后看成员函数在类的继承后有无可能被更改功能,如果希望更改其功能的,一般应该将它声明为虚函数。如果成员函数在类被继承后功能不需修改,或派生类用不到该函数,则不要把它声明为虚函数。

虚函数对于多态具有决定性的作用,有虚函数才能构成多态,这节我们来重点说一下虚函数的注意事项。

1) 只需要在虚函数的声明处加上 virtual 关键字,函数定义处可以加也可以不加。

2) 为了方便,你可以只将基类中的函数声明为虚函数,这样所有派生类中具有遮蔽(覆盖)关系的同名函数都将自动成为虚函数。

3) 当在基类中定义了虚函数时,如果派生类没有定义新的函数来遮蔽此函数,那么将使用基类的虚函数。

4) 只有派生类的虚函数遮蔽基类的虚函数(函数原型相同)才能构成多态(通过基类指针访问派生类函数)。例如基类虚函数的原型为virtual void func();,派生类虚函数的原型为virtual void func(int);,那么当基类指针 p 指向派生类对象时,语句p -> func(100);将会出错,而语句p -> func();将调用基类的函数。

5) 构造函数不能是虚函数。对于基类的构造函数,它仅仅是在派生类构造函数中被调用,这种机制不同于继承。也就是说,派生类不继承基类的构造函数,将构造函数声明为虚函数没有什么意义。

6) 析构函数可以声明为虚函数,而且有时候必须要声明为虚函数。

构造函数和析构函数能否声明为虚函数?

答:构造函数不能声明为虚函数,析构函数可以声明为虚函数,而且有时是必须声明为虚函数。

构造函数不能声明为虚函数的原因是:

解释一:所谓虚函数就是多态情况下只执行一个。而从继承的概念来讲,总是要先构造父类对象,然后才能是子类对象。如果构造函数设为虚函数,那么当你在构造父类的构造函数时就不得不显示的调用构造。还有一个原因就是为了防错,试想如果你在子类中一不小心重写了个跟父类构造函数一样的函数,那么你的父类的构造函数将被覆盖,也即不能完成父类的构造.就会出错。

解释二:虚函数的主要意义在于被派生类继承从而产生多态。派生类的构造函数中,编译器会加入构造基类的代码,如果基类的构造函数用到参数,则派生类在其构造函数的初始化列表中必须为基类给出参数,就是这个原因。

析构函数设为虚函数的作用:

在类的继承中,如果有基类指针指向派生类,那么用基类指针delete时,如果不定义成虚函数,派生类中派生的那部分无法析构。

纯虚函数:

纯虚函数在基类中是没有定义的,必须在子类中加以实现。

如果基类含有一个或多个纯虚函数,那么它就属于抽象基类,不能被实例化

虚函数与纯虚函数有什么区别

答:

- 虚函数:如果一个类中声明了虚函数,这个函数是实现的,他的作用是为了能让这个函数在他的子类里面能被覆盖,这样就可以实现动态多态。

- 纯虚函数只是一个接口,是个函数的声明而已,他留在子类中实现。

- 虚函数在子类中可以不重载

- 纯虚函数必须在子类中实现

- 虚函数的类用作”实现继承“,即继承接口的同时也继承了父类的实现。

- 纯虚函数用于”介面继承“,即纯虚函数关注的是接口的统一性,实现由子类完成

- 带纯虚函数的类叫做虚基类,这种类不能直接生成对象。

分别简单讲述一下函数重载,函数覆盖,函数隐藏的概念与特征:

函数重载:重载函数通常用来命名一组功能相似的函数

1.函数要在相同的类域

2.函数的名字要相同

3.函数的参数列表或返回值不同

函数覆盖(重写):覆盖是指派生类函数覆盖基类函数

1.函数是要在不同的类域

2.两个函数的名称相同

3.两个函数的参数相同

4.基类函数必须是虚函数

函数隐藏:指派生类的函数屏蔽了与其同名的基类函数

1.两个函数在不同的类域

2.函数名称相同

3.函数参数不同

4.(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏。

(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏。

相关文章

  • 查漏补缺

    C++虚函数: 多态: 静态多态(重载)、动态多态(虚函数) 虚函数 虚函数表:编译器为每个类创建了一个虚函数表...

  • c++程序员面试宝典之多态与虚函数

    二十.多态与虚函数 多态:多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到...

  • 深刻剖析之c++博客文章

    三大特性 封装、继承、多态 多态 C++ 虚函数表解析C++多态的实现原理 介绍了类的多态(虚函数和动态/迟绑定)...

  • 2020-07-06----《C++类的学习》

    函数重载:同名不同参。 C++类的特点:封装、继承、多态。 //多态与函数重载是啥关系? 虚函数:和软件架构相关 ...

  • GeekBand-C++面向对象高级编程(下)-Week2

    对象模型:虚函数表(vtbl)与虚表指针(vptr) 我们知道,C++中,可以通过虚函数来实现多态性,而虚函数是通...

  • C++虚函数注意事项以及构成多态的条件

    C++ 虚函数对于多态具有决定性的作用,有虚函数才能构成多态。 虚函数注意事项 只需要在虚函数的声明处加上 vir...

  • c++面试问题总结

    1.c++面试问题总结:(1)空类的大小,仅含有虚函数类的大小(2)析构函数声明为虚函数的作用(3)C++多态的实...

  • 语法

    virtual 1.virtual声明的函数实现多态就是通用的多态实现 2.纯虚函数C++的纯虚函数用于表示一个类...

  • pwnable.kr之uaf && c++虚函数

    c++的逆向还是要熟悉下。 一、关于c++虚函数 虚函数使得c++能够实现多态,每个类有一个虚表,每个对象在实现的...

  • JAVA 虚函数、抽象函数、抽象类、接口

    Java 虚函数虚函数的存在是为了多态。C++中普通成员函数加上virtual关键字就成为虚函数Java中其实没有...

网友评论

      本文标题:c++程序员面试宝典之多态与虚函数

      本文链接:https://www.haomeiwen.com/subject/geixvftx.html