C++在虚函数和纯虚函数、普通函数的区别

        虚函数多态机制可以让成员函数操作一般化,用基类指针指向不同派生对象时,基类指针可以调用其派生对象的虚函数成员。

1.虚函数

        C++的虚函数作用主要是运行时多态,父类中提供虚函数的实现,为子类提供默认的函数实现。子类可以重写父类的虚函数,以实现子类的特殊化。

多态的关键之处,是通过一切指向基类的指针或引用来操作对象。

2.纯虚函数

        C++中的包含纯虚函数的类是抽象类,抽象类不能new出对象,只有实现了纯虚函数的子类才能new出对象。即只提供申明,没有实现,是对子类的约束,是“接口继承”。

3.普通函数

        普通函数是静态编译的,没有运行时多态,只会根据指针或引用的“字面值”类对象,调用自己的普通函数,普通函数是父类为子类提供的强制实现。

4.综合实例

#include <iostream>
using namespace std;

class A
{
public:
    virtual void out1()=0;  ///由子类实现
    virtual ~A(){};
    virtual void out2() ///默认实现
    {
        cout<<"A(out2)"<<endl;
    }
    void out3() ///强制实现
    {
        cout<<"A(out3)"<<endl;
    }
};

class B:public A
{
public:
    virtual ~B(){};
    void out1()
    {
        cout<<"B(out1)"<<endl;
    }
    void out2()
    {
        cout<<"B(out2)"<<endl;
    }
    void out3()
    {
        cout<<"B(out3)"<<endl;
    }
};

int main()
{
    A *ab=new B;
    ab->out1();
    ab->out2();
    ab->out3();
    cout<<"************************"<<endl;
    B *bb=new B;
    bb->out1();
    bb->out2();
    bb->out3();

    delete ab;
    delete bb;
    return 0;
}

        执行结果:

        B B A ****** B B B

        即静态编译的函数是根据指针的类型调用的,运行时多态的函数是根据new出的对象调用的。

        虚函数的目的是,不同父类指针指向同一子类实例,能够调用到实际的函数。

5.虚函数的实现机制

        C++的虚函数是通过一张虚函数表来实现的,这个表的内容就是虚函数的地址表,当我们用父类指针去操作一个子类的时候,根据这张表上的函数地址来调用函数。

        在类被继承时,如果某虚函数没有被覆盖,那么虚函数表中会增加原来没有的函数,而原来父类中虚函数的也依然存在。如果继承时,某虚函数被覆盖,那么虚函数表中对应的函数地址将被改变。在多重继承时,每个父类都有自己的虚函数表。

        这样做就是为了解决不同的父类类型的指针指向同一子类实例,能够得到调用到实际函数。

6.虚函数表的安全性问题

        通过父类的指针访问子类的虚函数会导致编译出错

        如果虚函数是private或者protected,那么可以通过虚函数表访问这些函数

        更详细的内容参见这篇博客

        OK,See You Next Chapter!

发表评论