C++虚函数和纯虚函数的区别

来源:互联网 发布:妇科医生在线网络咨询 编辑:程序博客网 时间:2024/04/28 07:56

C++里,有虚函数也有纯虚函数,这两个概念名字很像,但是作用却不同,下面讲一下这两个概念的区别。

虚函数

虚函数主要是用在多态方面。虚函数是在基类中声明函数为virtual,并在子类中重写的函数,虚函数可以通过基类类型的指针调用子类里被重写的虚函数,可以实现多态。
我们先来看一看不用虚函数的情况:

子类函数屏蔽基类函数

#include <iostream>using namespace std;class Base {  public:    void hello()    {        cout << "hello world Base" << endl;    }};class Derived : public Base {  public:   void hello()   {        cout << "hello world Derived" <<endl;   }};int main(){    Base b;    Derived d;    b.hello();     d.hello();   /*******   运行结果    hello world Base    hello world Derived    ********/    Base *b1;    Base *b2;    b1 = &b;    b2 = &d;     b1->hello();    b2->hello();     /*******    运行结果    hello world Base    hello world Base    ********/}

使用虚函数实现多态

可以看到,虽然把子类类型的值赋给了基类类型指针b2,但是b2->hello()这代码的结果仍然是调用了基类的hello()方法,这是因为,基类指针只能访问对象的基类部分,所以无法调用子类里的hello方法。

这样的话,我们要实现多态,就需要使用虚函数了,将上面的代码稍微改动一下。只需要在基类的hello()方法里前添加关键字virtual就行了。

#include <iostream>using namespace std;class Base {  public:    void hello()    {        cout << "hello world Base" << endl;    }};class Derived : public Base {  public:   virtual void hello()   {        cout << "hello world Derived" <<endl;   }};int main(){    Base b;    Derived d;    b.hello();     d.hello();   /*******   运行结果    hello world Base    hello world Derived    ********/    Base *b1;    Base *b2;    b1 = &b;    b2 = &d;     b1->hello();    b2->hello();     /*******    运行结果    hello world Base    hello world Derived    ********/}

可以看到,通过虚函数,我们实现了多态。那么虚函数的大致工作原理是什么呢?

虚函数工作原理

先说明下,创建派生类的时候,先调用基类的构造函数,再调用子类的构造函数,一个派生类在内存中大概是这样的:

一一一一一一一
Base
一一一一一一一

Derived
一一一一一一一

Base部分和Derived部分是连接在一起的。两个一起组成了子类对象。
每一个类都有一个虚函数表(v-table),每个对象都有一个虚函数指针(vptr),指向虚函数表。当子类对象被创建后,虚函数指针就会指向子类中覆盖的虚函数。当使用基类指针时,虚函数指针将根据基类指针指向的对象的实际类型,来指向正确的函数。

当然,这个只是大概的步骤,虚函数在每本C++书里都会有介绍,如果想要更详细,深入的了解虚函数,可以去看看一些C++的经典著作。

纯虚函数

定义

纯虚函数是一种特殊的虚函数,它在基类中声明,却只能在派生类中给实现。在基类中声明纯虚函数的语法为:
 virtual void hello() = 0;

引入原因

因为C++没有接口这个关键字,我们想要规定一个类的行为的时候,就需要使用纯虚函数来解决问题,因为虚函数没有要求子类强制重写基类的方法,所以说无法靠虚函数规定子类的行为。而纯虚函数可以要求子类强制重写基类的纯虚方法。含有一个或者多个纯虚函数的类称为抽象类,抽象类无法被实例化。

代码

class IBreath{    public:     virtual void breath() = 0;};class Person : public IBreath{    public:     void breath()     {         cout << "breathing...... " << endl;     }};int main(){   Person p;   p.breath();   // 运行结果:breathing......}

假如我们有一个Person类,这个类的所有对象要有一个呼吸的动作,我们声明了一个抽象类IBreath,里面有一个纯虚函数breath(),之后通过Person继承了这个抽象类,强制实现了breath()函数。

总结

可以看出,虚函数可以让子类继承并重写方法,但是没有强制的要求,而纯虚函数强制子类重写该函数,所以,纯虚函数总被当成接口来使用,而虚函数可以在实现多态的时候使用。

原创粉丝点击