使用抽象类时,如何正确删除指针
How to properly delete pointers when using abstract classes
假设我有以下类和对象:
#include <iostream>
class Animal
{
public:
virtual void makeNoise() = 0;
void eat()
{
std::cout << "Eating..." << "n";
}
void sleep()
{
std::cout << "Sleeping..." << "n";
}
};
class Cat: public Animal
{
public:
void makeNoise()
{
std::cout << "Miow..." << "n";
}
};
class Cow: public Animal
{
public:
void makeNoise()
{
std::cout << "Mooo..." << "n";
}
};
int main()
{
Animal *animal;
Cat *cat = new Cat();
Cow *cow = new Cow();
animal = cat;
animal->eat();
animal->sleep();
animal->makeNoise();
animal = cow;
animal->eat();
animal->sleep();
animal->makeNoise();
return 0;
}
请注意,动物是抽象类。
如何正确删除指针animal
,cat
和cow
?
当我尝试使用delete animal;
时,我会收到以下警告消息:
警告:删除具有抽象类类型的"动物"的对象 非虚拟破坏者将导致不确定的行为。
另一方面,当我尝试使用delete cat;
时,我会收到以下消息:
警告:删除具有多态类类型的对象" cat" 非虚拟破坏者可能会导致不确定的行为。
基本的C 规则说,破坏者从派生的类到基类方面的工作方式。当Cat
被销毁时,Cat
部分首先被销毁,并且Animal
部分被破坏。
delete animal;
是未定义的行为,因为要正确遵循C 破坏规则,必须在运行时知道,在Animal
基本部分之前,应将其派生的类零件销毁。virtual
驱动器确实可以做到这一点 - 它启用了一种动态调度机制,以确保破坏按设计工作。
您没有virtual
破坏者,因此delete animal
只是没有意义。没有办法调用正确的派生级破坏者,只销毁Animal
部分也不是有意义的行为。
因此,C 语言对在这种情况下会发生什么没有任何假设。
您的编译器足以警告您。
使用delete cat
,情况略有不同。cat
指针的静态类型是Cat*
,而不是Animal*
,因此即使没有任何动态调度机制,也很明显,该机制衍生了级别的驱动器,请先调用。
编译器仍然警告您有关此的信息,但是它以不同的措辞(可能是" vs."会导致")这样做)。我相信原因是Cat
本身可能是派生类的基类,因为它已经是具有virtual
功能的类层次结构的一部分。
显然不费心执行更完整的代码分析,以发现delete cat
确实是无害的。
为了解决此问题,请制作Animal
Destructor virtual
。当您使用时,用std::unique_ptr
替换原始指针。您仍然必须遵循像您这样的类的virtual
驱动器规则,但您不再需要执行手册delete
。
这正是编译器警告您的内容。您需要为每个类定义和实现自己的攻击子,并确保将其定义为virtual
的继承。
- 如何正确删除这些指针?
- 从 QAbstractItemModel 中正确删除子树
- 正确删除с++中的类
- 何时/如何在使用指针后正确删除指针?
- 如何正确删除 std::string 数组
- 如何在单链列表 c++ 中正确删除节点
- 如何正确删除具有已知二维大小的二维数组
- C :如何正确删除在类破坏者中的指针
- 如何正确删除一行控件并在该位置动态创建一个新控件
- 我是否正确删除了指向对象的指针向量?
- 如何在C 中正确删除树
- 使用抽象类时,如何正确删除指针
- BST 节点删除 - 指针未正确删除
- C++应用程序:如何正确删除/释放已分配的对象
- 如何从动态内存中正确删除对象的指针
- C 正确删除动态分配的内存
- 如何正确删除是中央小部件的Qgraphicsview对象
- 如何在C++中正确删除链表的节点
- 正确删除向量的元素
- 正确删除EGL Opengles 2.0