虚析构与纯虚析构(C++)

纯虚函数和抽象类

概念

首先引入“纯虚函数”和“抽象类”的概念,示例代码如下

#include<iostream>
using namespace std;
class Base  //抽象类
{
public:
    virtual void func() = 0;    //纯虚函数
};
class Son1:public Base
{
public:
    void func()
    {
        cout << "func()调用" << endl;
    }
};
void test01()
{
    //Base b;//抽象类无法实例化对象
    Base* b = new Son1; //父类指针指向子类对象
    b->func();
}
int main()
{
    test01();
    system("pause");
}

运行结果如下:

file

其中,virtual void func() = 0;称为纯虚函数,也即是在成员函数的开头加上virtual关键词,且没有函数实现,取而代之的是末尾的=0;,而一旦类中有一个纯虚函数,则该类被称为抽象类,抽象类具有以下特点:

  • 抽象类无法实例化对象
  • 抽象类的子类必须重写父类中的纯虚函数,否则也为抽象类

目的

纯虚函数和抽象类的存在是为了更好的契合多态的思想。关于多态,简而言之就是用父类的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数

问题

纯虚函数的使用也会带来某些问题,由于实际调用时是父类指针指向子类对象,因此如果在子类中开辟了堆区数据,在析构时父类指针无法指向子类对象,即子类的析构函数不能够正常的被调用,这会带来内存泄漏的问题。例如下列代码:

#include<iostream>
using namespace std;
class Animal
{
public:
    Animal()
    {
        cout << "Animal构造函数调用" << endl;
    }
    ~Animal()
    {
        cout << "Animal析构函数调用" << endl;
    }
    virtual void speak() = 0;
};
class Cat :public Animal
{
public:
    Cat(string name)
    {
        //子类中存在堆区数据
        cName = new string(name);
        cout << "Cat构造完成" << endl;
    }
    void speak()
    {
        cout << *cName << "猫在叫" << endl;
    }
    ~Cat()
    {
        if (cName != NULL)
        {
            delete cName;
            cName = NULL;
            cout << "Cat析构完成" << endl;
        }
    }
    string* cName;
};
void test01()
{
    Animal* a = new Cat("Tom");
    a->speak();
    delete a;
}
int main()
{
    test01();
    system("pause");
}

运行结果如下:

file

可以看到子类Cat的析构函数并未调用,要想解决该问题就需要继续引入“虚析构”与“纯虚析构”。

虚析构与纯虚析构

虚析构

虚析构的实现与虚函数一致,只需要在父类的析构函数前面加上virtual关键字即可,只需要将前面代码中的Animal基类改成:

class Animal
{
public:
    Animal()
    {
        cout << "Animal构造函数调用" << endl;
    }
    virtual ~Animal()   //加virtual关键词变成虚析构
    {
        cout << "Animal虚析构函数调用" << endl;
    }
    virtual void speak() = 0;
};

此时运行结果为:

file

可以看到此时的Cat正常析构,堆区数据被正常释放!

纯虚析构

与纯虚函数实现类似,将Animal基类做如下改动:

class Animal
{
public:
    Animal()
    {
        cout << "Animal构造函数调用" << endl;
    }
    virtual ~Animal() = 0;  //纯虚析构
    virtual void speak() = 0;
};
//必须类外实现
Animal::~Animal()
{
    cout << "Animal纯虚析构函数调用" << endl;
}

值得注意的是,纯虚析构必须在类外具体实现,否则将无法完成编译。拥有纯虚析构的类也叫做抽象类,无法实例化对象。

本文作者:小小黑
本文链接:https://lonelyenderman.top/archives/762
版权声明:本站采用 BY-NC-SA 进行许可。转载请注明出处!
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(*^▽^*)
 ̄﹃ ̄
(╯‵□′)╯︵┴─┴
(~ ̄▽ ̄)~
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
( ͡° ͜ʖ ͡°)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
つ﹏⊂
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
(´▽`ʃ♡ƪ)
w(゚Д゚)w
(๑•̀ㅂ•́)و✧
(#`O′)
凸(艹皿艹 )
o(≧口≦)o
≡ω≡
(*/ω\*)
○| ̄|_
(⊙ˍ⊙)
Σ(っ °Д °;)っ
o( ̄ヘ ̄o#)
<( ̄︶ ̄)>
(。・∀・)ノ゙
(o゜▽゜)o☆
╥﹏╥
ヾ(´・ω・`)ノ
😂
😀
😅
😊
🙂
😍
😘
😜
😝
😏
😒
🙄
😳
😔
😫
😱
😭
😶
🌚
😣
🤨
😣
🤐
😪
🤤
🥵
🤮
😨
😱
😓
🤬
👴
🤡
🙈
💊
🙏
🤺
💩
👻
🙌
🖕
👍
👫
👌
🙏
👀
🐒
🔪
Source: github.com/zhheo/Sticker-Heo
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
Heo
花!
上一篇
下一篇