tags:

views:

10654

answers:

7

I have defined an interface in c++, i.e. a class containing only pure virtual functions.

I want to explicitly forbid users of the interface to delete the object through a pointer to the interface, so I declared a protected and non-virtual destructor for the interface, something like:

class ITest{
public:
    virtual void doSomething() = 0;
protected:
    ~ITest(){}
};

void someFunction(ITest * test){
    test->doSomething(); // ok
    // deleting object is not allowed
    // delete test; 
}

The GNU compiler gives me a warning saying "class 'ITest' has virtual functions but non-virtual destructor".

Once the destructor is protected, what is the difference in having it virtual or non-virtual?

Do you think this warning can be safely ignored or silenced?

A: 

If the destructor is virtual it makes sure that the base class destructor is also called fore doing the cleanup, otherwise some leaks can result from that code. So you should make sure that the program has no such warnings (prefferably no warnings at all).

Iulian Şerbănoiu
+6  A: 

Some of the comments on this answer relate to an earlier answer I gave, which was wrong.

A protected destructor means that it can only be called from a base class, not through delete. That means that an ITest* cannot be directly deleted, only a derived class can. The derived class may well want a virtual destructor. There is nothing wrong with your code at all.

However, since you cannot locally disable a warning in GCC, and you already have a vtable, you could consider just making the destructor virtual anyway. It will cost you 4 bytes for the program (not per class instance), maximum. Since you might have given your derived class a virtual dtor, you may find that it costs you nothing.

Airsource Ltd
I always wonder why the destructor is not always virtual ...
Iulian Şerbănoiu
2 reasons. (1) You only pay for what you use in C++. If the dtor was virtual then lots of classes would have unneccessary vtables. (2) Certain frameworks (eg. CORBA) I believe are now dependent on the current behaviour.
Richard Corden
Richard and Airsource, I removed the comments that referred to the previous answer. I now have no problems with your answer and changed my initial -1 to a +1...
Len Holgate
There won't be any run time overhead for marking the base's destruct virtual here, regardless of whether the derived class destructor is virtual, since it would only come into play when polymorphically deleting from the base. Since this can't happen due to protected... (except maybe delete this)
Greg Rogers
Sure there's no CPU overhead unless the function is actually called in a manner involving a vtable lookup. There will be 4 bytes of overhead though, as the vtable will be 4 bytes larger by virtue of having an additional virtual function.
Airsource Ltd
A: 

If you had code in one of ITest's methods that tried to delete itself (a bad idea, but legal), the derived class's destructor wouldn't be called. You should still make your destructor virtual, even if you never intend to delete a derived instance via a base-class pointer.

Adam Rosenfield
No he shouldn't. The contract of the interface that he's defined is that users of the interface can't delete instances of objects that implement it. It's quite a common pattern for objects that are allocated and cleaned up via a factory or via reference counting... (-1)
Len Holgate
+20  A: 

It's more or less a bug in the compiler. Note that in more recent versions of the compiler this warning does not get thrown (at least in 4.3 it doesn't). Having the destructor be protected and non-virtual is completely legitimate in your case.

See here for an excellent article by Herb Sutter on the subject. From the article:

Guideline #4: A base class destructor should be either public and virtual, or protected and nonvirtual.

Greg Rogers
I believe it's only a warning - and the above case is the exceptional one. In general if you have virtual functions you probably should also have a virtual destructor.
Richard Corden
I agree it is a minor bug that the warning isn't suppressed in the presence of a protected destructor. The other answers mentioning deletion by a derived class are valid, but it's much less likely to be problematic than regular missing virtual destructors.
James Hopkin
Thanks for the link to Herb's article!
Len Holgate
typo?: "having the constructor be protected...", I assume you meant 'destructor'. Edit?
jwfearn
Nice catch jwfearn. Thanks.
Greg Rogers
This is bug 7302: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=7302
CesarB
A: 

If you insist on doing this, go ahead and pass -Wno-non-virtual-dtor to GCC. This warning doesn't seem to be turned on by default, so you must have enabled it with -Wall or -Weffc++. However, I think it's a useful warning, because in most situations this would be a bug.

bk1e
+1  A: 

It's an interface class, so it's reasonable you should not delete objects implementing that interface via that interface. A common case of that is an interface for objects created by a factory which should be returned to the factory. (Having objects contain a pointer to their factory might be quite expensive).

I'd agree with the observation that GCC is whining. Instead, it should simply warn when you delete an ITest*. That's where the real danger lies.

MSalters
+2  A: 

My personal view is that you'd doing the correct thing and the compiler is broken. I'd disable the warning (locally in the file which defines the interface) if possible,

I find that I use this pattern (small 'p') quite a lot. In fact I find that it's more common for my interfaces to have protected dtors than it is for them to have public ones. However I don't think it's actually that common an idiom (it doesn't get spoken about that much) and I guess back when the warning was added to GCC it was appropriate to try and enforce the older 'dtor must be virtual if you have virtual functions' rule. Personally I updated that rule to 'dtor must be virtual if you have virtual functions and wish users to be able to delete instances of the interface through the interface else the dtor should be protected and non virtual' ages ago ;)

Len Holgate