首页 > 编程知识 正文

析构函数可以声明为虚函数,整个业务准则体系的核心

时间:2023-05-05 23:05:43 阅读:168453 作者:3136

http://www.Sina.com/http://www.Sina.com /

shoulddestructionbehavevirtually? That is,shoulddestructionthroughapointertoabaseclassbeallowed? If yes,then base ' sdestructormustbepublicinordertobecallable, andvirtualotherwisecallingitresultsinundefinedbehavior.otherwisecallingitresultsinundefinedbehavior.othertuavi itshouldbepre sescaninvokeitintheirowndestructors,and non-virtualsinceitdoesn ' tneedtobehavevirtuave

析构函数应该是虚函数吗? 也就是说,是否应该允许使用指向基类的指针进行销毁? 在这种情况下,base析构函数必须是公共的才能调用。 否则,虚拟调用将导致未定义的行为。 否则,必须保护只有派生类才能在自己的析构函数中调用。 此外,此析构函数也必须是非虚的,因为它不需要虚拟地执行。

Discussion: Make base class destructors public and virtual, or protected and non-virtual

thecommoncaseforabaseclassisthatit ' sintendedtohavepubliclyderivedclasses,andsocallingcodeisjustaboutsuretousesomethinglike

基类的常见用法是拥有公共派生类。 因此,您可以通过调用代码来使用shared_ptr base等内容。

class Base {public: ~Base (; //BAD,not virtual virtual ~Base (; //GOOD //.}; class derived : public base {/*…*/}; { unique _ ptrbasepb=make _ unique derived (; /////~pbinvokescorrectdestructoronlywhen~baseisvirtualinrarercases,such as policy classes,theclassisusedasabaseclaseclasses notforpolymorphicbehavior.itisrecommendedtomakethosedestructorsprotectedandnon-1

在极少数情况下(如策略类),为了方便起见,此类用作基类而不是多态性行为。 建议保护析构函数和进行非虚拟化。

class my _ policy { public : virtual~my _ policy (; //BAD,publicandvirtualprotected :至my _ policy (; //GOOD //.}; templateclasspolicyclasscustomizable : policy {/*…*/}; //note : private inheritance http://www.Sina.com /

thissimpleguidelineillustratesasubtleissueandreflectsmodernusesofinheritanceandobject-orienteddesignprinciples。

这个简单的准则说明了微妙的问题,反映了继承和面向对象设计原则的现代用法。

For a base classBase,callingcodemighttrytodestroyderivedobjectsthroughpointerstobase,suchaswhenusingaunique _ ptr base.if base

hat actually points to a derived object, in which case the behavior of the attempted deletion is undefined. This state of affairs has led older coding standards to impose a blanket requirement that all base class destructors must be virtual. This is overkill (even if it is the common case); instead, the rule should be to make base class destructors virtual if and only if they are public.

对于基类Base,调用代码可能会尝试通过指向Base的指针销毁派生对象,例如在使用unique_ptr <Base>时。如果Base的析构函数是公共的和非虚拟的(默认值),则可能会意外地在实际上指向派生对象的指针上调用它,在这种情况下,尝试删除的行为是不确定的。这种情况导致较早的编码标准对所有基类析构函数都必须是虚拟的提出了全面的要求。这太过分了(即使是常见情况);相反,规则应该是当且仅当基类析构函数是公共的时,才将它们虚函数化。

To write a base class is to define an abstraction (see Items 35 through 37). Recall that for each member function participating in that abstraction, you need to decide:

编写基类就是定义一个抽象(请参阅第35到37项)。回想一下,对于参与该抽象的每个成员函数,您需要确定:

Whether it should behave virtually or not.

它是否应该表现为虚函数。

Whether it should be publicly available to all callers using a pointer to Base or else be a hidden internal implementation detail.

是否应该使用指向Base的指针将其公开给所有调用者使用,还是作为隐藏的内部实现细节。

As described in Item 39, for a normal member function, the choice is between allowing it to be called via a pointer to Base non-virtually (but possibly with virtual behavior if it invokes virtual functions, such as in the NVI or Template Method patterns), virtually, or not at all. The NVI pattern is a technique to avoid public virtual functions.

如第39项所述,对于普通成员函数,选择之间是允许以非虚拟方式(通过指向Base的指针)调用它(但如果它调用虚拟函数(例如在NVI或模板方法模式中),则可能具有虚拟行为) ),实际上还是根本没有。NVI模式是一种避免公开虚函数的技术。

Destruction can be viewed as just another operation, albeit with special semantics that make non-virtual calls dangerous or wrong. For a base class destructor, therefore, the choice is between allowing it to be called via a pointer to Base virtually or not at all; "non-virtually" is not an option. Hence, a base class destructor is virtual if it can be called (i.e., is public), and non-virtual otherwise.

析构可以看作只是另一种操作,尽管具有使非虚调用变得危险或错误的特殊语义。因此,对于基类析构函数,选择是根据是否允许通过指向Base的指针实际上调用它。“非虚”不是一种选择。因此,如果可以调用(即是公共的)基类析构函数,则它是虚拟的,否则是非虚拟的。

Note that the NVI pattern cannot be applied to the destructor because constructors and destructors cannot make deep virtual calls. (See Items 39 and 55.)

注意,NVI模式不能应用于析构函数,因为构造函数和析构函数无法进行深度虚拟调用。(请参阅第39和55条。)

 

Corollary: When writing a base class, always write a destructor explicitly, because the implicitly generated one is public and non-virtual. You can always=defaultthe implementation if the default body is fine and you're just writing the function to give it the proper visibility and virtuality.

推论:编写基类时,请始终显式编写一个析构函数,因为隐式生成的是公共的和非虚的。如果默认函数就很好,那么您只需要决定器可见性和虚函数性,则实现可以直接使用=default。

Exception(例外)

Some component architectures (e.g., COM and CORBA) don't use a standard deletion mechanism, and foster different protocols for object disposal. Follow the local patterns and idioms, and adapt this guideline as appropriate.

某些组件体系结构(例如COM和CORBA)不使用标准的删除机制,而是使用不同的协议来处理对象。遵循特定情况的模式和习惯用法,并适当修改此准则。

Consider also this rare case:

 

还要考虑这种罕见的情况:

 

B is both a base class and a concrete class that can be instantiated by itself, and so the destructor must be public for B objects to be created and destroyed.

B是可以自己实例化的基类和具体类,因此析构函数必须是公共的,才能创建和销毁B对象。

Yet B also has no virtual functions and is not meant to be used polymorphically, and so although the destructor is public it does not need to be virtual.

但是B也没有虚函数,并且不打算被多态使用,因此尽管析构函数是公共的,但它并不需要是虚的。

Then, even though the destructor has to be public, there can be great pressure to not make it virtual because as the first virtual function it would incur all the run-time type overhead when the added functionality should never be needed.

然后,即使析构函数必须是公共的,也可能会面临很大的,不将其虚函数化的压力,因为作为第一个虚拟函数,当永远不需要添加的功能时,它将招致所有运行时类型的开销。

In this rare case, you could make the destructor public and non-virtual but clearly document that further-derived objects must not be used polymorphically as B's. This is what was done with std::unary_function.

在这种罕见的情况下,您可以将析构函数设为公共的和非虚拟的,但要清楚地表明,不允许将衍生出的对象用作B的多态形式。这正是std :: unary_function的功能。

In general, however, avoid concrete base classes (see Item 35). For example, unary_function is a bundle-of-typedefs that was never intended to be instantiated standalone. It really makes no sense to give it a public destructor; a better design would be to follow this Item's advice and give it a protected non-virtual destructor.

 

但是,通常应避免使用具体的基类(请参阅第35项)。例如,unary_function是typedef的捆绑包,不能独立实例化。给它一个公开的析构函数确实没有任何意义。更好的设计是遵循该产品的建议,为其提供受保护的非虚析构函数。

 

原文链接https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#discussion-make-base-class-destructors-public-and-virtual-or-protected-and-non-virtual

新书介绍

《实战Python设计模式》是作者最近出版的新书,拜托多多关注!

本书利用Python 的标准GUI 工具包tkinter,通过可执行的示例对23 个设计模式逐个进行说明。这样一方面可以使读者了解真实的软件开发工作中每个设计模式的运用场景和想要解决的问题;另一方面通过对这些问题的解决过程进行说明,让读者明白在编写代码时如何判断使用设计模式的利弊,并合理运用设计模式。

对设计模式感兴趣而且希望随学随用的读者通过本书可以快速跨越从理解到运用的门槛;希望学习Python GUI 编程的读者可以将本书中的示例作为设计和开发的参考;使用Python 语言进行图像分析、数据处理工作的读者可以直接以本书中的示例为基础,迅速构建自己的系统架构。

 

 

觉得本文有帮助?请分享给更多人。

关注微信公众号【面向对象思考】轻松学习每一天!

面向对象开发,面向对象思考!

 

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。