这是抽象的,但具有非虚拟析构函数删除会导致错误。这是为什么?

问题描述 投票:0回答:2
#include <iostream> 
using namespace std;

class Animal{
public:
 virtual void cry() = 0;
 void eat();
};


class Cat:public Animal
{
public:
        virtual void cry();
        void grooming();
};


class Dog:public Animal
{
public:
        virtual void cry();
        void lash();
};


main()
{
    Animal* animal = new Cat();
    animal->eat();
    animal->cry();

    Cat* cat = (Cat*)animal;
    cat->grooming();

    Dog* dog = new Dog();
    dog->cry();
    dog->eat();
    dog->lash();

    delete animal;     //Delete called on'animal' that is abstract but has non-virtual destruct
    delete cat;             //Thread 1: signal SIGABRT
    delete dog;
}

删除导致错误。这是为什么? 尝试在不使用析构函数的情况下通过delete释放内存,但出现错误 "删除名为'animal'的抽象但具有非虚拟析构的对象 线程 1:信号 SIGABRT"

c++
2个回答
13
投票

该错误告诉您问题是什么。您正在使用非虚拟析构函数销毁虚拟对象。

你有

virtual void cry
为什么?这样,当您调用
animal->cry
时,它会调用
Cat
哭声,而不是默认的
Animal
哭声。虚拟析构函数也是如此。当您调用
delete animal
时,您需要它来调用实际对象的析构函数,而不仅仅是基类。您需要添加:

virtual ~Animal() = default;

到你的动物课。

base类析构函数应该是公共和虚拟的,或者是受保护的和非虚拟的

Cpp 核心指南

至于第二期,双重删除:

delete animal; // deletes the object
delete cat; // deletes the same object again, because cat and animal point to 
            // the same place.

有些人建议不要删除两次,我建议根本不要显式调用删除。使用智能指针:

auto cat = std::make_unique<Cat>();
Animal &animal = *cat;

animal.cry();
cat->cry(); // Calls the same function as above.

唯一的指针将为您处理对象的删除。


0
投票

您尝试两次删除同一个对象:

Animal* animal = new Cat();

Cat* cat = (Cat*)animal;   // cat points to the same object as animal
...
delete animal;     // first delete
delete cat;        // second attemp fails
© www.soinside.com 2019 - 2024. All rights reserved.