C++多态、抽象类、虚函数和虚析构

分类:

静态多态: 函数重载 和 运算符重载属于静态多态,复用函数名。        编译阶段确定函数地址

动态多态: 派生类和虚函数实现运行时多态                                           运行阶段确定函数地址

C++可以进行 父子之间的类型转换,一个全局函数形参是父类,可以生成一个子类对象直接传入作为实参,但是此时对于父类子类的同名函数,首先应该调用的是父类的成员函数,因为此情况属于地址早绑定(因为该全局函数的参数是父类地址,在编译阶段就确定)

解决该情况就应该使用虚函数构建动态多态,在父类同名函数前加入virtual,使其在运行阶段再确定函数地址,根据传入对象的不同来确定不同的地址

(重写的概念:不同于重载,其函数返回值类型、函数名、参数列表都完全相同)

此处要保证子类成员函数于和父类成员函数是重写的关系

上述动态多态的使用条件:父类指针或者引用指向子类对象   Base * p = new Son; delete p;

虚函数的内存占用:

对于如下一个示例类:

class animal {

public:

    void speak()

    {

        cout <<"111"<<endl;

    }    

};

其内存占用为1,因为属于一个空类,其成员函数不属于类的内存空间(非静态成员函数、静态成员函数、静态成员变量都不属于)

此时其成员函数若变为虚函数:

class animal {

public:

    virtual void speak()

    {    
        cout <<"111"<<endl;

    }    

};

则该类的内存占用为4,因为本质是一个指针(指针无论什么类型都是占用4字节(32位系统、VS编译)),如果是64位系统,占用8字节

纯虚函数和抽象类:

纯虚函数来源于:父类中的虚函数一般不会被实例化、无意义,主要都是调用子类重回的内容,则其可以写为纯虚函数:

virtual 返回值类型 函数名(参数列表) = 0 ;

如果一个类中有纯虚函数,则类也成为抽象类

抽象类无法被实例化、其子类必须要重写抽象类中的纯虚函数,否则也属于抽象类,无法实例化

理解为虚函数存在的意义就在于让子类重写该函数

虚析构和纯虚析构:

多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码

父类指针在析构的时候,不会调用子类中的析构函数,导致子类如果在堆区有属性会内存泄漏

解决方式:将父类中的析构函数改为虚析构或者纯虚析构

virtual ~Base( ) { ... } 

虚析构和纯虚析构共性:
1、可以解决父类指针释放子类对象

2、都需要有具体的函数实现虚析构和纯虚析构区别:
如果是纯虚析构,该类同样属于抽象类,同样无法实例化对象

纯虚析构:

virtual ~Base( ) =0;

但是与前面纯虚函数不同的是,纯虚析构和虚析构不仅要有代码声明也要有代码具体内容实现

注意:虚析构和纯虚析构都是为了解决子类中的堆区数据无法释放的问题,如果子类中没有new,则可以不写这俩

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值