C/C++教程

【C++面试】虚函数和纯虚函数

本文主要是介绍【C++面试】虚函数和纯虚函数,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

小米二面

在牛客网上的C++面筋题。

1. 虚函数和纯虚函数的区别

  • 因为写代码时不能在一开始就确定被调用的是基类的函数,还是哪个派生类的成员函数,所以C++通过虚函数实现多态,即在基类中用virtual声明,父类可以引用子类对象,子类成员函数可以重写父类方法(函数)。虚函数的核心理念就是通过基类访问派生类定义的函数。
    • 析构函数应当是虚函数,将调用相应对象类型的析构函数,因此,如果指针指向的是子类对象,将调用子类的析构函数,然后自动调用基类的析构函数。
    • 定义一个函数为虚函数,不代表函数为不被实现的函数。定义他为虚函数是为了允许用基类的指针来调用子类的这个函数。

在这里插入图片描述

  • 定义一个函数为纯虚函数,才代表函数没有被实现。纯虚函数没有函数体,同时在基类声明时需要在函数原型后加上=0。如上所示:
    • 在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。所以出现【抽象类】(含有纯虚函数的类)就规定不能实例化为对象。
    • 纯虚函数是为了安全,因为避免任何需要明确但是因为不小心而导致的未知的结果,提醒子类去做应做的实现。

【纯虚函数的实现原理】
纯虚函数也一定是某个类的成员函数,含有纯虚函数的类叫做抽象类。在C++中,抽象类无法实例化对象。如果我们定义了Shape这样的类,那么,Shape类当中,因为有虚函数和纯虚函数,所以它一定有一个虚函数表,也就一定有一个虚函数表指针。在虚函数表当中,如果是纯虚函数,那么虚函数表中的函数指针值为0;如果是普通的虚函数,那就肯定是一个有意义的值。
在这里插入图片描述
一个虚函数的最简单的栗子:

#include <iostream>
using namespace std;

class A{
public:
    virtual void foo()
    {
        cout<<"A::foo() is called"<<endl;
    }
};
class B:public A
{
public:
    void foo()
    {
        cout<<"B::foo() is called"<<endl;
    }
};
int main(void)
{
    A *a = new B();
    a->foo();   // 在这里,a虽然是指向A的指针,但是被调用的函数(foo)却是B的!
	system("pause");
    return 0;
}

在这里插入图片描述

2. 构造函数能不能是虚函数

不能。。C++在编译期间,就能确定你要创建的对象的具体类型,而这个具体类型包含了什么,继承了什么在编译期间也是明确的,即构建一个对象,必须知道具体的类型信息,构造什么也都是明确的,根本没必要存在虚构造函数。虚函数的存在是因为编译期间没法确定具体调用对象,才会有虚函数,虚函数表这么个东西。

解决方案:Bjarne建议用factory pattern,也就是为每一个要构建的类型再创建一个对应的factory,把问题放到factory的make方法中去解决。这也是C++中的通用解决方案。

Reference

[1] https://www.zhihu.com/question/35632207

这篇关于【C++面试】虚函数和纯虚函数的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!