我对大多数OO理论有了深刻的理解,但让我困惑的一件事是虚拟析构函数.
我认为无论什么以及链中的每个对象,析构函数总是会被调用.
你什么时候打算让它们成为虚拟的?为什么?
我知道在C++中为基类声明虚拟析构函数是一个好习惯,但是virtual
即使对于作为接口的抽象类来说,声明析构函数总是很重要吗?请提供一些理由和示例原因.
是否有充分的理由不为类声明虚拟析构函数?什么时候应该特别避免写一个?
如果我有一个带有虚拟析构函数的基类.有一个派生类来声明一个虚拟析构函数吗?
class base {
public:
virtual ~base () {}
};
class derived : base {
public:
virtual ~derived () {} // 1)
~derived () {} // 2)
};
Run Code Online (Sandbox Code Playgroud)
具体问题:
虚拟析构函数声明后的覆盖标识符是否有任何特殊含义?
class Base
{
public:
virtual ~Base()
{}
virtual int Method() const
{}
};
class Derived : public Base
{
public:
virtual ~Derived() override
{}
virtual int Method() override // error: marked override, but does not override - missing const
{}
};
Run Code Online (Sandbox Code Playgroud)
在虚方法上使用覆盖标识符作为检查非常有用:当Base虚方法实际上未被覆盖时,编译器将报告错误.
虚拟析构函数上的覆盖是否也有任何含义/功能?
Java和C#支持的,不能用作与基类类的概念 final
和sealed
关键字.但是,在C++中,如果每个类都有一个虚拟的析构函数,那么就没有什么好的方法可以防止类的派生出于某种困境而导致类被派生出来?
编辑:从C++ 11开始,这不再是真的,你可以指定一个类final
.
一方面给一个对象一个虚拟析构函数意味着它将拥有一个vtable
并因此消耗4个(或64位机器上的8个)每个对象的附加字节vptr
.
另一方面,如果有人后来从这个类派生并通过指向基类的指针删除派生类,程序将是错误定义的(由于没有虚拟析构函数),并且坦率地优化每个对象的指针是荒谬.
在具有虚拟析构函数的抓握手上(可以说是)宣称这种类型意味着多态地使用.
有些人认为,你需要一个明确的理由不使用虚拟析构函数(如的潜台词这个问题)和其他人说,只有当你有理由相信,你的类是从派生你应该使用它们,有什么事你认为?
可能重复:
何时使用虚拟析构函数?
您的C++对象的析构函数何时应该virtual
?
在这些关于C++ 11/14标准的幻灯片中,在幻灯片15中,作者写道"C++ 11中的许多经典编码规则不再适用".他提出了三个例子清单,我同意三条规则和内存管理.
然而他的第二个例子是"虚拟析构函数与虚拟成员"(就是这样).这是什么意思?我知道必须声明为基类析构函数的虚拟,以便在我们有类似的东西时调用正确的析构函数
Base *b = new Derived;
...
delete b;
Run Code Online (Sandbox Code Playgroud)
这里有很好的解释:什么时候使用虚拟析构函数?
但是,如果你有虚拟成员,现在在C++ 11中声明虚拟你的析构函数是没用的吗?
灵感来自帖子为什么析构函数会禁用隐式移动方法的生成?,我想知道默认的虚拟析构函数是否也是如此,例如
class WidgetBase // Base class of all widgets
{
public:
virtual ~WidgetBase() = default;
// ...
};
Run Code Online (Sandbox Code Playgroud)
由于该类旨在成为窗口小部件层次结构的基类,因此我必须定义其析构函数virtual,以避免在使用基类指针时出现内存泄漏和未定义的行为.另一方面,我不想阻止编译器自动生成移动操作.
默认的虚拟析构函数是否会阻止编译器生成的移动操作?
之前可能已经问过这个问题,但是我无法找到类似的问题.
考虑以下类层次结构:
class BritneySpears
{
public:
virtual ~BritneySpears();
};
class Daughter1 : public BritneySpears
{
public:
virtual ~Daughter1(); // Virtual specifier
};
class Daughter2 : public BritneySpears
{
public:
~Daughter2(); // No virtual specifier
};
Run Code Online (Sandbox Code Playgroud)
Daughter1
和Daughter2
班级有区别吗?
指定/不指定virtual
子类析构函数/方法会产生什么后果?
谢谢.