views:

365

answers:

4

I didnt see it in the C++ Faq lite

How do i define a base class so every class inheriting it is required to define a destructor?

I tried running this program

struct VDtor { virtual ~VDtor()=0;  };
struct Test:VDtor { virtual ~Test(){}  };
int main() { delete new Test; return 0; }

http://codepad.org/wFcE71w3 With the error

In function `Test::~Test()':
t.cpp:(.gnu.linkonce.t._ZN4TestD0Ev+0x1e): undefined reference to `VDtor::~VDtor()'
In function `Test::~Test()':
t.cpp:(.gnu.linkonce.t._ZN4TestD1Ev+0x1e): undefined reference to `VDtor::~VDtor()'

So, is it possible?

+14  A: 

It is "possible" in some sense (if your goal was that the derived class stays abstract otherwise). But it won't give the result you would like: Because the compiler will create a destructor itself implicitly if the programmer hasn't done so.

It's therefor not possible to force the derived class' author to explicitly declare a constructor.

(edit: Like @chubsdad notes noted, the error in your particular code is because you need to define the explicitly declared destructor of the base class).


Edit: Just for fun, there are situations that necessiate an explicitly declared constructor. Consider the following

struct Viral {
  struct Dose { };
protected:
  ~Viral() throw (Dose) { }
};

struct Base {
  virtual ~Base() throw() { }
};

struct Derived : Base, Viral { };

This code won't compile because the implicitly declared ~Derived will have an exception specification throw (Dose) which is looser than what ~Base has - so it violates the requirement that overriders shall not have a looser exception specification. You will need to explicitly declare the destructor appropriately

struct Derived : Base, Viral { ~Derived() throw() { } };

But this is not really a solution to your problem, because derived classes need to "cooperate" into either deriving from Viral or putting it as a non-static data member. It's also very ugly :)


Edit: The following seems to be a Standard conforming way to do it

struct Viral {
  struct Dose { };
protected:
  ~Viral() throw (Dose) { }
};

struct Base : virtual Viral {
  virtual ~Base() throw() { }
};

Clang and GCC (starting with v4.6) reject any derived class of Base that has an implicitly declared destructor, because it has an incompatible exception specification (any derived class shall call ~Viral directly, instead of indirectly by calling ~Base, the Standard says). Comeau accepts this, but I strongly suspect that it is non-conforming in this regard.

Johannes Schaub - litb
+1: I completely forgot about the implicit destructor while responding to this.
Chubsdad
So does this mean No it isnt possible to force a derive class to define a dtor?
acidzombie24
@acid i would say it is not possible to force the programmer to explicitly define a destructor in a derived class. Can you please show what you need this for?
Johannes Schaub - litb
i wrote a comment below the question.
acidzombie24
@Johannes Schaub - litb: Sorry, I deleted my post to avoid confusion on wrong information. Probably you can remove reference to my post also
Chubsdad
@Chubsdad thanks, done.
Johannes Schaub - litb
You should probably say No instead of "Yes it is possible" because my question is about forcing derive to define dtors which apparently is not possible.
acidzombie24
@acid i have adjusted my answer to be more clear. I see that it could have yielded to confusion.
Johannes Schaub - litb
Johannes Schaub - litb: i see. Can you change your answer to more clearly reflect that? That was the reason why i havent accepted it. Because when i read it; to me it appeared you were saying i could forced derived classes to define it but i wont get results i want due to some implicitly created destructors which doesnt make sense bc why would they be generated if i am forced to define it. This only made sense after i read other answers/comments when i realize you meant yes force virtaul destructors which is what i asked in the title but not in main body which i thought you were answering.
acidzombie24
A: 

Every class has a destructor, regardless. Declaring a virtual destructor in the base ensures that children will have virtual destructors. This doesn't mean that the coder will need to explicitly declare a destructor -- that wouldn't be a good thing, anyhow. All it means is that, if a destructor is declared, it will be virtual.

Steven Sudit
A: 

When Test is destructed, it will call it's base class destructor, which doesn't exist. You should just declare it empty if you have no necessary destruction logic.

DeadMG
+1  A: 
struct VDtor { virtual ~VDtor()=0;  };
VDtor::~VDtor () { } // <== Implementation.
struct Test:VDtor { ~Test(){}  };
int main() { delete new Test; return 0; }

To fix the error you have to actually implement the VDtor::~VDtor() like above.

wilx
But that doesnt force derive class to implement their own destructor.
acidzombie24
@acidzombie24: Either a class needs non-empty dtor and then nothing the base can do will help or the implicit and empty dtor is good enough and then there is no point in spelling it out explicitly, IMHO.
wilx