多态的整体认识(虚函数篇)

1.虚函数(重写的好兄弟):

  虚函数是多态的得力助手之一。可以在子类继承到父类的成员函数时,在不改函数名的情况下,将他的功能重新定义,为己所用。
  要注意的是,被static修饰的静态成员函数,被inline修饰的内联函数,构造函数不可以被声明为虚函数。当在基类的成员函数类型前加了virtual修饰后,继承他的子类中重写时也会自动加上。

class A
{
    public:
        virtual void func()
        {
            cout<<"A"<<endl;
        }
}

2.虚析构函数

  在继承中,将析构函数声明为虚析构函数是至关重要的,很多初学者往往忽视这一问题。平常写一些小程序一般是看不出有何问题的,但是这是非常危险的操作。先看一个例子:

#include <iostream>

using namespace std;

class A
{   
    public:
        A()
        {
            cout<<"contructor A!"<<endl;
        }
        virtual void func()
        {
            cout<<"A"<<endl;
        }
        ~A()
        {
            cout<<"destructor A!"<<endl;
        }
};

class B:public A
{
    public:
        B()
        {
            cout<<"contructor B!"<<endl;
        }
        void func()
        {
            cout<<"B"<<endl;
        }
        ~B()
        {
            cout<<"destructor B!"<<endl;
        }
};

int main()
{
    A *a=new B;
    a->func();
    delete a;
    return 0;
}

输出结果:

contructor A!
contructor B!
B
destructor A!

  我们会发现系统只调用了A类的析构函数,而没有调用B类的,当我们在堆中自己分配了一块空间,我们就得在操作完成之后及时回收,不然会导致内存的泄露。上述例子就出现了这一问题。

#include <iostream>

using namespace std;

class A
{   
    public:
        A()
        {
            cout<<"contructor A!"<<endl;
        }
        virtual void func()
        {
            cout<<"A"<<endl;
        }
        virtual ~A()
        {
            cout<<"destructor A!"<<endl;
        }
};

class B:public A
{
    public:
        B()
        {
            cout<<"contructor B!"<<endl;
        }
        void func()
        {
            cout<<"B"<<endl;
        }
        ~B()
        {
            cout<<"destructor B!"<<endl;
        }
};

int main()
{
    A *a=new B;
    a->func();
    delete a;
    return 0;
}

输出结果:

contructor A!
contructor B!
B
destructor B!
destructor A!

  利用虚析构函数就能很好地解决这一问题。这是初学者很难注意到的问题,我要不是写这篇博客,可能也会经常疏忽。

3.纯虚函数:

  纯虚函数,看上去比虚函数纯一点,也就是虚函数没有了函数体。其实,它的作用和虚函数是有很大不同的。

class A
{
    public:
        virtual void func()=0;
}

  包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能定义抽象类的对象。基类中的纯虚函数在被子类中被定义。除非在子类中完全实现基类中所有的纯虚函数,否则,派生类也变成了抽象类,不能实例化对象。
  比如声明基类为形状,形状并不是具体的对象,但是不管什么形状都有其面积。我们可以声明一个求面积的纯虚函数。之后再声明一个子类为正方形,在正方形类中,如果不对求面积函数进行重写,将其定义,编译时将会报错。

#include<iostream>

using namespace std;

class Line
{
    protected:
        float len;//长
    public:
        Line(float len):len(len){}
        virtual float area()=0;//表面积
        virtual float volume()=0;//体积
        virtual ~Line(){};
};

class Rec:public Line
{
    protected:
        float width;//宽
    public:
        Rec(float len,float width):Line(len),width(width){}
        float area()
        {
            return len*width;
        }
        ~Rec(){};
};

class Cuboid:public Rec
{
    protected:
        float hight;
    public:
        Cuboid(float len,float width,float hight):Rec(len,width),hight(hight){}
        float area()
        {
            return 2*(len*width+len*hight+width*hight);
        }
        float volume()
        {
            return len*width*hight;
        }
        ~Cuboid(){};
};

class Cube:public Cuboid
{
    public:
        Cube(float len):Cuboid(len,len,len){}

        float area()
        {
            return 6*len*len;
        }
        float volume()
        {
            return len*len*len;
        }
        ~Cube(){};
};

int main()
{
    Line *p=new Cuboid(1,2,3);//长方体

    cout<<"Cuboid area:"<<p->area()<<endl;
    cout<<"Cuboid volume:"<<p->volume()<<endl;

    delete p;

    //p=new Rec(1,2);//未定义volume,为抽象类,编译会报错

    p=new Cube(3);//正方体

    cout<<"Cube area:"<<p->area()<<endl;
    cout<<"Cube volume:"<<p->volume()<<endl;

    delete p;

    return 0;
}

  纯虚函数的作用是为派生类提供一个一致的接口。所以他更像是基类给子类分配任务,也可以起到提示的作用。因为你如果没有完成任务,编译时就会报错。
  就好像抽象类(基类)是个工程师,纯虚函数是建筑图纸。工程师绘制好图纸,然后图纸交给工人(也就是子类)。工程师只负责画图,他并不会垒砖建墙。而工人照着图纸建筑,合理分工,才能最终完成任务。

总结

  很多人对多态不甚了解,很多概念容易弄混,希望看了文章可以给你带来帮助。还有虚析构函数的声明是最容易被人所遗忘的,像我们这些初学者一定要特别注意。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值