When should your destructor be virtual?
Possible Duplicate:
When to use virtual destructors?
什么时候C++对象的析构函数应该是EDOCX1?0?
这是因为虚拟方法的原因是您想要使用多态性。这意味着您将在基类指针上调用一个方法,并且需要最派生的实现——这是多态性的全部要点。
现在,如果没有虚拟析构函数,并且通过指向基类的指针调用析构函数,那么最终将调用基类析构函数。在这种情况下,您希望多态性也能在析构函数上工作,例如,通过在基类上调用析构函数,您希望最终调用最派生类的析构函数,而不是基类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class A { virtual void f() {} ~A() {} } class B : public A { void f() {} ~B() {} } A * thing = new B(); thing->f(); // calls B's f() delete thing; // calls ~A(), not what you wanted, you wanted ~B() |
使~a()虚拟打开多态性
1 | virtual ~A() {} |
所以当你现在打电话的时候
1 | delete thing; |
将调用~b()。
当您将类设计为一个接口时(例如,您希望它被扩展或实现),您将声明虚拟析构函数。在这种情况下,一个好的做法是使用一个接口类(在Java接口的意义上)使用虚拟方法和虚拟析构函数,然后有具体的实现类。
您可以看到STL类没有虚拟析构函数,因此它们不应该被扩展(例如std::vector、std::string…)。如果扩展std::vector并通过指针或引用调用基类上的析构函数,则绝对不会调用专门的类析构函数,这可能导致内存泄漏。
从Stroustrup的C++风格和技巧谈起:
So when should I declare a destructor
virtual? Whenever the class has at
least one virtual function. Having
virtual functions indicate that a
class is meant to act as an interface
to derived classes, and when it is, an
object of a derived class may be
destroyed through a pointer to the
base.
关于你的析构函数在C++ FAQ中应该是虚拟的很多额外信息。(谢谢)
什么是虚拟成员?从C++常见问题解答:
[20.1] What is a"virtual member function"?
From an OO perspective, it is the
single most important feature of C++:
[6.9], [6.10].A virtual function allows derived
classes to replace the implementation
provided by the base class. The
compiler makes sure the replacement is
always called whenever the object in
question is actually of the derived
class, even if the object is accessed
by a base pointer rather than a
derived pointer. This allows
algorithms in the base class to be
replaced in the derived class, even if
users don't know about the derived
class.The derived class can either fully
replace ("override") the base class
member function, or the derived class
can partially replace ("augment") the
base class member function. The latter
is accomplished by having the derived
class member function call the base
class member function, if desired.
I've recently come to conclude that the fully correct answer is this:
Guideline #4: A base class destructor
should be either public and virtual,
or protected and nonvirtual.
当然,赫伯萨特给出了他的主张的理由。注意,他确实超出了通常的答案"当某人通过基类指针删除派生类对象"和"如果类有任何虚拟函数,则使析构函数成为虚拟的"。
如果要(甚至可能)通过基类指针销毁派生类的对象,则需要一个虚拟析构函数。
我采用的方法是,如果我要从一个类派生,那么它将有一个虚拟析构函数。实际上,在我编写的代码中,没有哪种情况会影响到虚拟析构函数的性能,即使在今天实际上不需要它,在将来修改类时,它也可能最终需要它。
基本上:将虚拟化放到所有的基类析构函数上,除非您有一个好的、经过深思熟虑的理由不这样做。
这只是另一条经验法则,但它能防止你以后犯错误。
总是。
除非我真正关心vtable的存储和性能开销,否则我总是将其虚拟化。除非您有一个静态分析工具来验证您的析构函数在正确的情况下是虚拟的,否则不值得犯错误,也不值得在需要时不创建虚拟析构函数。
当基类需要自己进行清理时,基类对象应该有一个虚拟析构函数。也就是说,如果已经在基类中分配了资源,则必须通过声明其析构函数virtual来清理该基类,从而确保将完成此清理(假设您正确编写了清理)。
通常,方法可以在基类中定义为虚拟的,这将允许派生类重写虚拟方法,实现它们自己的派生特定实现。我发现这是用一个简单的例子最清楚地证明的。假设我们有一个基类"shape",现在所有派生类都可能需要有绘制的能力。"shape"对象将不知道如何绘制从它派生的类,因此在"shape"类中,我们定义一个虚拟绘制函数。ie(virtual void draw();)。现在,在每个基类中,我们可以覆盖这个函数,实现特定的绘图代码(即,正方形与圆形的绘制方式不同)。