• C++中对C的扩展学习新增内容———面向对象(继承)纯虚函数和虚析构函数以及纯虚析构函数


    纯虚函数和虚析构函数以及纯虚析构函数

    纯虚函数(抽象类):

    1、当一个类包含了纯虚函数,这个类就不能用来创建对象了。这个类叫做抽象类。

    2、当一个类继承了父类的话,必须去重写父类的纯虚函数。如果子类不重写父类的纯虚函数,子类仍然是抽象类。

    3、纯虚函数的实现:

    class Animal
    {
    public:
        virtual void speak() = 0;  // 纯虚函数
    };

    虚析构函数以及纯虚析构函数:

    1、通过父类指针释放子类对象问题

    class Animal
    {
    public:
    
        Animal()
        {
            cout << "Animal 构造函数" << endl;
            p_name = new char[100];
        }
    
        virtual void speak()
        {
            cout << "Animal 说话..." << endl;
        }
    
        // virtual ~Animal() {}
        // virtual ~Animal() = default;  //C++11
    
        virtual ~Animal()
        {
            cout << "Animal 析构函数" << endl;
            if (p_name != nullptr)
            {
                delete[] p_name;
                p_name = nullptr;
            }
        }
    public:
        char *p_name;
    };
    
    
    class Dog : public Animal
    {
    public:
        Dog()
        {
            cout << "Dog 构造函数" << endl;
            p_name2 = new char[100];
        }
    
        virtual void speak()
        {
            cout << "Dog 说话..." << endl;
        }
    
        ~Dog()
        {
            cout << "Dog 析构函数" << endl;
            if (p_name2 != nullptr)
            {
                delete[] p_name2;
                p_name2 = nullptr;
            }
        }
    public:
        char *p_name2;
    };
    
    
    void test01()
    {
        // 父类构造 子类构造
        Animal *animal = new Dog;
        animal->speak();
    
        // 
        delete animal;
    
        // 当多态发生时,如果通过父类指针去释放子类对象,默认情况只会调用父类的析构函数。可能会导致内存泄漏。
    }

    当多态发生时如果通过父类指针去释放子类对象,默认情况只会调用父类的析构函数。可能会导致内存泄漏。

    2、虚析构函数的作用(通过父类指针去释放子类对象)没如果要实现多态,最好父类中增加一个虚析构函数。

    3、虚析构函数和纯虚析构函数

    (1) 纯虚析构函数要在类外增加函数体。

    (2) 如果类的内部写了纯虚析构函数,该类就是抽象类(不能被实例化)。

    (3) 一般情况下,写虚析构函数即可,类的内部有很多带有实现的虚函数,此时又希望该类为抽象类,此时我们可以将析构函数设置为纯虚析构函数,使得该类变成抽象类。

    class Animal
    {
    public:
    
        Animal()
        {
            cout << "Animal 构造函数" << endl;
            p_name = new char[100];
        }
    
        virtual void speak()
        {
            cout << "Animal 说话..." << endl;
        }
    
        virtual ~Animal() = 0;  // 纯虚析构函数
    public:
        char *p_name;
    };
    
    Animal::~Animal()
    {
    
    }
    
    
    class Dog : public Animal
    {
    public:
        Dog()
        {
            cout << "Dog 构造函数" << endl;
            p_name2 = new char[100];
        }
    
        virtual void speak()
        {
            cout << "Dog 说话..." << endl;
        }
    
        ~Dog()
        {
            cout << "Dog 析构函数" << endl;
            if (p_name2 != nullptr)
            {
                delete[] p_name2;
                p_name2 = nullptr;
            }
        }
    public:
        char *p_name2;
    };
    
    void test02()
    {
        Animal *animal = new Dog;
        animal->speak();
    
        delete animal;
    }
  • 相关阅读:
    UML期末复习题——2.7:UML Sequence Diagram
    UML期末复习题——2.6:Package Diagram
    UML期末复习题——2.5:System Sequence Diagram & Post-condition
    UML期末复习题——2.4:Domain Model
    UML期末复习题——2.3:UML State Diagram
    UML期末复习题——2.2:UML Activity Diagram.
    UML期末复习题——2.1:Use Case Diagram
    UML期末复习题
    《C++之那些年踩过的坑(附录一)》
    《C++之那些年踩过的坑(三)》
  • 原文地址:https://www.cnblogs.com/yyslif/p/11892504.html
Copyright © 2020-2023  润新知