你的析构函数什么时候应该是虚拟的?
可能的重复:
何时使用虚拟析构函数?
C++ 对象的析构函数何时应为虚拟< /代码>?
Possible Duplicate:
When to use virtual destructors?
When should your C++ object's destructor be virtual
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
至少一个类方法是
虚拟的。
这是因为虚方法的原因是要使用多态性。 这意味着您将调用基类指针上的方法,并且您想要最派生的实现 - 这就是多态性的全部要点。
现在,如果您没有虚拟析构函数,并且通过指向基类的指针调用析构函数,则最终会调用基类析构函数。 在这种情况下,您希望多态性也适用于您的析构函数,例如,通过在基类上调用析构函数,您希望最终调用最派生类而不是基类的析构函数。
具有 ~A() 虚拟会开启多态性,
因此当您现在调用
~B() 时,将调用 ~B() 。
当您将类设计为接口时,您将声明虚拟析构函数,例如您希望扩展或实现它。 在这种情况下,一个好的做法是拥有一个带有虚拟方法和虚拟析构函数的接口类(在 Java 接口的意义上),然后拥有具体的实现类。
您可以看到,STL 类没有虚拟析构函数,因此不应扩展它们(例如 std::vector、std::string ...)。 如果您扩展 std::vector 并通过指针或引用调用基类的析构函数,您肯定不会调用专门的类析构函数,这可能会导致内存泄漏。
least one of class methods is
virtual.
This is because the reason for virtual method is that you want to use polymorphism. Meaning you will call a method on the base class pointer and you want the most derived implementation - this is the whole point of polymorphism.
Now if you did not have virtual destructor and through the pointer to base class you call destructor you end up calling base class destructor. In this case you want polymorphism to work on your destructor as well, e.g. through calling destructor on your base class you want to end up calling destructor of your most derived class not your base class.
having ~A() virtual turns on polymorphism
So when you now call
~B() will be called.
You would declare virtual destructors when you design class as an interface e.g. you expect it to be extended or implemented. A good practice in that case is to have a interface class (in the sense of Java interfaces) with virtual methods and virtual destructor and then have concrete implementation classes.
You can see that STL classes don't have virtual destructors so they are not supposed to be extended (e.g. std::vector, std::string ...). If you extend std::vector and you call destructor on base class via pointer or reference you will definitely not call your specialized class destructor which may lead to memory leaks.
来自 Stroustrup 的 C++ 风格和技术常见问题解答:
关于当你的析构函数应该是虚拟的时,有很多附加信息C++ 常见问题解答。 (感谢 Stobor)
什么是虚拟会员? 来自 C++ 常见问题解答:
From Stroustrup's C++ Style and Technique FAQ:
Lots of additional info on when your destructor should be virtual on the C++ FAQ. (thanks Stobor)
What is a virtual member? From the C++ FAQ:
当然Herb Sutter 给出了理由对他的主张。 请注意,他确实超出了通常的答案“当有人通过基类指针删除派生类对象时”和“如果您的类有任何虚函数,则使您的析构函数成为虚拟的”。
And of course Herb Sutter gives the rationale to his claim. Note that he does go beyond the usual answers "when someone will delete a derived-class object via a base-class pointer" and "make your destructor virtual if your class has any virtual functions".
如果您将(甚至可能)通过基类指针销毁派生类的对象,则需要一个虚拟析构函数。
我采取的方法是,如果我要从一个类派生,那么它应该有一个虚拟析构函数。 在我编写的代码中,实际上没有任何情况表明虚拟析构函数对性能影响很重要,即使现在实际上不需要它,将来当类被修改时也可能需要它。
基本上:将 virtual 放在所有基类析构函数上,除非您有充分的、经过深思熟虑的理由不这样做。
这只是另一条经验法则,但可以防止您以后再犯错误。
If you will (or even might) destroy objects of a derived class through a base class pointer, you need a virtual destructor.
I take the approach that if I'm going to derive from a class AT ALL, then it shall have a virtual destructor. There are effectively no cases in the code I write where the performance implications of a virtual destructor matter, and even if it's not actually needed today, it might end up needing it in the future when the class is modified.
Basically: Put virtual on all base class destructors unless you have a good, well-thought out reason not to.
That's just another rule of thumb, but it's one that keeps you from making later mistakes.
总是。
除非我真的关心 vtable 的存储和性能开销,否则我总是将其虚拟化。 除非您有一个静态分析工具来验证您的析构函数在正确的情况下是虚拟的,否则犯错误并且在需要时未能创建虚拟析构函数是不值得的。
Always.
Unless I'm really concerned with the storage and performance overhead of a vtable, I always make it virtual. Unless you have a static analysis tool to verify for you that your destructor is virtual in the right cases, it's not worth making a mistake and failing to make a virtual destructor when it's needed.
当基类需要进行自己的清理时,基类对象应该有一个虚拟析构函数。 这就是说,如果您在基类中分配了资源,则基类有必要进行清理,通过将其析构函数声明为虚拟,您可以保证此清理将完成(假设您正确编写了清理)。
一般来说,可以在基类中定义虚拟方法,这将允许派生类覆盖虚拟方法,实现自己的派生特定实现。 我发现通过一个简单的例子可以最清楚地证明这一点。 假设我们有一个基类“Shape”,现在可能要求所有派生类都具有绘图能力。 “Shape”对象不知道如何绘制从它派生的类,因此在“Shape”类中我们定义了一个虚拟绘制函数。 即(虚拟无效绘制();)。 现在,在每个基类中,我们可以重写此函数,实现特定的绘图代码(即,正方形的绘制方式与圆形不同)。
A base class object should have a virtual destructor, when it is necessary for the base class to do its own cleanup. This is to say, if you have allocated resources in the base class it is necessary for the base class to cleanup, by declaring its destructor virtual you guarantee that this cleanup will be done (assuming you wrote the cleanup correctly).
In general, methods can be defined virtual in a base class, this will allow derived classes to override the virtual methods, implementing their own derived specific implementation. I find this is most clearly demonstrated with a simple example. Say we have a base class 'Shape', now all derived classes may be required to have the ability to draw. The 'Shape' object will not know how to draw classes derived from it, so in the 'Shape' class we define a virtual draw function. ie (virtual void draw();). Now in each base class we can override this function, implementing specific drawing code (ie. a square is drawn differently from a circle).