我真的已经完成了现有的问题,我仍然需要回答这个问题才能真正了解我是否理解这一点。
通常,我们定义自己的析构函数的唯一时间是在内存上动态分配内容。
但是,我们仍然需要实现我们自己的析构函数(即使在堆上没有动态分配)只是为了将其命名为虚拟(如果我们没有在堆上分配任何内容,它可以只是纯虚拟的)使用基类地址(指针/引用)来访问派生类的对象。这是(我的推论)无条件正确吗?
因为如果有:
Base* p = new Derived;
现在要删除p,即空闲内存,我们必须将析构函数声明为虚拟并执行:
delete p;
正确?
答案 0 :(得分:1)
Base* p = new Derived;
现在要删除p,即空闲内存,我们必须将析构函数声明为虚拟并执行:
delete p;
正确的吗?
是强>
作为这个问题的答案(Does delete work with pointers to base class?也说明了。
是的,当且仅当基类析构函数是虚拟
时才会起作用
如果析构函数的实现很简单,你可以这样做
virtual ~Base() = default;
此外,派生类型应该使用override
。
virtual ~Derived() override = default;
^^^1^^^ ^^^2^^^^
// 1: Optional because the base destructor is virtual
// 2: The compiler will verify the base destructor is virtual
答案 1 :(得分:0)
是。最好假设存在需要运行析构函数的子类,因此虚拟析构函数需要存在于Base
中。此外,即使在任何析构函数中没有代码的情况下,预计在销毁时也会发生其他事情。
class Derived : public Base {
MyMember m;
}
如果Base
上没有虚拟析构函数,当您以多态方式删除m
时,永远不会调用Base*
的析构函数。
如果您计划允许Base
为任意子类进行子类化,则需要Base
具有虚拟析构函数,以便安全地删除这些子类。
不建议考虑Base
的非虚拟析构函数,因为您需要保证所有子类不仅没有析构函数,而且它们都没有析构函数的成员 ...这意味着没有stl容器或对象中的任何其他东西。其他开发人员很容易忽略这些奇怪的需求,因此您应该在Base
中拥有一个虚拟析构函数。
答案 2 :(得分:0)
您只需要使基类的析构函数为虚拟。派生类可以显式定义析构函数,也可以使用构造函数定义的隐式析构函数。
struct Base
{
virtual ~Base() {}
};
struct Derived1 : public Base
{
// Explicitly defined destructor.
// Use of virtual is optional.
~Derived () {}
std::vector<std::string>> data;
};
struct Derived2 : public Base
{
// Use the compiler defined destructor
std::vector<int>> data;
};
用法:
Base* p = new Derived1;
...
delete p; // OK
p = new Derived2;
...
delete p; // OK