开发者

what to do with the destructors in an interface

开发者 https://www.devze.com 2023-02-18 07:47 出处:网络
When I write interface classes in C++, I choose either of the following 2 options class Interface { p开发者_JS百科ublic:

When I write interface classes in C++, I choose either of the following 2 options

class Interface
{
p开发者_JS百科ublic:
   virtual R1 f1(p11, p12 , ...) = 0;
   ...
   virtual Rn fn(pn1, pn2 , ...) = 0;
   virtual ~Interface() {} 
}

or

class Interface
{
public:
   virtual R1 f1(p11, p12 , ...) = 0;
   ...
   virtual Rn fn(pn1, pn2 , ...) = 0;
   virtual ~Interface() = 0; 
}
Interface::~Interface() {}

The first version is shorter to write

The second is attractive in that all functions of the interface are pure virtual

Is there any reason I should prefer one or the other method (or perhaps a third one)?

Thanks


As I understand, the purpose of making virtual function pure virtual is to force the derived classes to either provide implementation for it or choose the default implementation by explicitly writing Base::f() in the Derived::f().

So if that is true, then what is the purpose of making virtual destructor pure virtual? Does it force the derived classes to provide implementation for Base::~Base()? Can the derived classes implement Base::~Base()? No.

So that means, the first version with virtual destructor seems enough for almost all purposes. After all, the most common purpose of virtual destructor is that the clients can correctly delete objects of the derived classes through pointers of type Base*.

However, if you make all functions in Base virtual only, not pure virtual, and provide implementations for them (actually you've to provide), and at the same time you want to make Base abstract type, then having a pure virtual destructor in Base is the only solution:

class Base
{
public:
   virtual void f() {}; //not pure virtual
   virtual ~Base() = 0; //pure - makes Base abstract type!
};

Base::~Base() {} //yes, you have to do this as well.

Base *pBase = new Base(); // error - cannot create instance!

Hope that helps.


To me, the dtor is not part of the interface. The fi() would have analogues in other languages, not the dtor. Likewise, you could write pre- and post- conditions for the fi(), but not the dtor. This makes it just a C++ wart, and the first technique is the most comfortable way of dealing with it.


Okay, found a link and so thought I would mention it as an answer:

Are inline virtual functions really a non-sense?

I've seen compilers that don't emit any v-table if no non-inline function at all exists (and defined in one implementation file instead of a header then). They would throw errors like missing vtable-for-class-A or something similar, and you would be confused as hell, as i was.

Indeed, that's not conformant with the Standard, but it happens so consider putting at least one virtual function not in the header (if only the virtual destructor), so that the compiler could emit a vtable for the class at that place. I know it happens with some versions of gcc. (Johannes Schaub)

Its slightly different from your second case (suggests actually taking the function out of the header file altogether so as not to fall victim to gcc problem) but I thought I would mention it. Quirks of gcc can occasionally bite.


In the first case, the derived class may choose whether or not to implement a destructor. In the second case, the pure virtual destructor must be overridden, so the derived class is forced to implement a destructor.

Unless you have some reason why you want to force this, I would go with the first case.

0

精彩评论

暂无评论...
验证码 换一张
取 消