Necessity of pure virtual destructor?

M

meadori

Razvan said:
That depends. There are two kinds of abstract classes in C++: classes
that don't have any state and all their methods are pure virtual
(similar to Java interfaces), and classes that have some state and/or
some of the behaviour already implemented (similar to Java abstract
classes - this is the kind of stuff you'd use, for example, to implement
the Template pattern).

In both cases, you _should_ add a virtual destructor. If you don't add a
virtual destructor, then deleting a derived class instance through a
pointer to a base class spells trouble. For more information on this,
you could check out Scott Meyers' books "Exceptional C++" and "More
Exceptional C++".
Not that it is that big of a deal, but Herb Sutter wrote "Exceptional
C++" and "More Exceptional C++" and not Scott Meyers. Meyers wrote
"Effective C++", "More Effective C++", and "Effective STL". The series
names are easy to confuse:).


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
M

Mike Smith

John said:
It is perhaps worth pointing out that this pure virtual function will
need an implementation in the base class.

Which, of course, can simply do nothing, if no action is called for:

ABC::~ABC() {}
 
L

Le Chaud Lapin

Martin said:
Absolutely. You can't create a class without a constructor or without
a destructor. (If you don't specify one, the compiler will do it for
you.)

Not to be pedantic, but the compiler can tell from the class definition
whether a a destructor is needed or not:

struct Foo
{
} ;

int main ()
{
Foo foo;
return 0;
}

// Assembly language output:

struct Foo
{
} ;

int main ()
{
00411F40 push ebp
00411F41 mov ebp,esp
00411F43 sub esp,0CCh
00411F49 push ebx
00411F4A push esi
00411F4B push edi
00411F4C lea edi,[ebp-0CCh]
00411F52 mov ecx,33h
00411F57 mov eax,0CCCCCCCCh
00411F5C rep stos dword ptr [edi]
Foo foo;
return 0;
00411F5E xor eax,eax
}
00411F60 push edx
00411F61 mov ecx,ebp
00411F63 push eax
00411F64 lea edx,ds:[411F78h]
00411F6A call @ILT+605(@_RTC_CheckStackVars@8) (411262h)
00411F6F pop eax
00411F70 pop edx
00411F71 pop edi
00411F72 pop esi
00411F73 pop ebx
00411F74 mov esp,ebp
00411F76 pop ebp
00411F77 ret

-Chaud Lapin-


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
K

Kodt

Destructor is a must. Because you must allow user to delete the object
I take it you mean "...to delete a derived-class object via a pointer to a
base-class object"?

That's what a _virtual_ destructor gives you the aility to do. It's not a
requirement if you don't need to do that, and it needs to be declared
virtual in order to accomplish that.

In fact, a virtual destructor provides a correct interface for 'delete
the_plain_pointer_to_base_class' operation.
If you don't expect to do this, you may leave the destructor to be
nonvirtual and even implicitly defined.

1) Scalarly deleted objects (allocated on stack, or static, or members
of other objects).

void foo(Base& obj); // will call some obj->method() that should be
virtual
int main() { Derived obj; foo(obj); }

2) Objects have a custom deletion function. Most known example is
IUnknown::Release that implementation deals with the final class, not
with a base.

A modification of this example: a smart pointer that knows the deleter.

template<class B, class D>
void delete_derived(B* b) { delete static_cast<D*>(b); }

shared_ptr<Base> p (new Derived(), delete_derived<Base,Derived>)


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
G

Greg Comeau

Not to be pedantic, but the compiler can tell from the class definition
whether a a destructor is needed or not:

// Assembly language output: ..ASM CODE SNIPPED...

True, but to be even more pedantic :), that's an optimization
on the generated code and does not negate other rules, etc.
--
Greg Comeau / Celebrating 20 years of Comeauity!
Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
K

kanze

Not that it is that big of a deal, but Herb Sutter wrote
"Exceptional C++" and "More Exceptional C++" and not Scott
Meyers. Meyers wrote "Effective C++", "More Effective C++",
and "Effective STL". The series names are easy to confuse:).

The obvious solution is to read both:). For the type of
questions posed by the original poster, "Effective C++" is the
essential book; it treats the simplest, lowest level questions,
such as when do you need a constructor or a destructor.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
K

kanze

Greg said:
True, but to be even more pedantic :), that's an optimization
on the generated code and does not negate other rules, etc.

According to the language rules, a class always has a
constructor and a destructor (which is what Greg is saying).
The standard does distinguish between trivial and non-trivial
constructors and destructors, however -- you cannot put a class
with a non-trivial constructor or destructor in a union, for
example. Since the compiler must make this distinction, it
would be perfectly surprising if it actually generated any code
for a trivial constructor or destructor. For that matter: given
that the compiler generated defaults are inline, what code could
it possibly generate. When you inline an empty function,
there's not much left.

Of course, there's no concept of "the compiler knowing whether a
destructor is needed or not". I'm not even sure what that
really means.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
R

Razvan Cojocaru

That's "Effective C++" and "More Effective C++".

Yes, you're right. Somebody else also pointed that out. Easy to confuse
names and a tight schedule tends to do that to people.
[...]
And you must _always_ provide a virtual destructor if your class is
meant as a base class for some other class (which it surely is, since
it's abstract).


Not if it the object of derived class is never deleted through a pointer
to the base class.

That's like saying that you only need to keep sharp objects from childen
if they intend to stick them in their eyeballs.
 
P

Pete Becker

Razvan said:
That's like saying that you only need to keep sharp objects from childen
if they intend to stick them in their eyeballs.

You must hang out with a bunch of rather bad programmers.
 
R

Razvan Cojocaru

Not that it is that big of a deal, but Herb Sutter wrote "Exceptional
C++" and "More Exceptional C++" and not Scott Meyers. Meyers wrote
"Effective C++", "More Effective C++", and "Effective STL". The series
names are easy to confuse:).

You're right, of course. I had a lot on my mind and it slipped :).

--
Razvan Cojocaru
KeyID: 1024D/04CA34DE

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
K

kanze

Ooops, I meant constructor.

But I still don't understand what it means to say "the compiler
knows whether it is needed or not". According to the language
definition, all classes have a constructor, which is used to
initialize the object. Some constructors are trivial, others
not; the language definition says which, and since what you can
do with an object partially depends on whether the constructor
is trivial or not, the compiler must be able to determine this.

All of which, of course, is irrelevant with regards to generated
code. Typically, if the constructor is inline, and not too
complicated, the compiler will inline it. (Trivial constructors
are always inline.) And if the constructor causes no code to be
generated (regardless of whether it is "trivial" in the language
sense of the word), the compiler will generate no code for it if
it inlined. That doesn't mean that the constructor or
destructor "aren't needed" -- I have a number of cases in my
code where constructors or destructors aren't trivial, and are
needed, but where the compiler doesn't generate any code for
them.

(I wonder if any compilers actually completely eliminate the
virtual destructor of an abstract class in which the destructor
doesn't do anything.)

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
M

Martin Bonner

WittyGuy said:
If destructor of either ABC or just base class needs to be virtual, why
don't we have virtual constructor?

You (and the compiler) always know the precise type of the object you
are creating at the point of creation, but if you delete an object
through a pointer to a base class you (and the compiler) do not
(necessarily) know the precise type of the object being destroyed.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
F

Francis Glassborow

If destructor of either ABC or just base class needs to be virtual, why
don't we have virtual constructor?

Because we construct things upwards but the compiler 'knows' where we
are aiming. We destroy things downwards but the compiler, given just a
pointer, does not know where the top is. Unless warned off it will use
the static type of the pointer rather than the dynamic type we require.


--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
K

kanze

WittyGuy said:
If destructor of either ABC or just base class needs to be
virtual, why don't we have virtual constructor?

Because the compiler needs an instance of an object in order to
resolve the virtuality. When you call a constructor, you don't
yet have an instance.

For that matter, it's not just a problem for the compiler. How
do I, the programmer, specify what type is to be constructed?

There is one exception where it might make sense: the copy
constructor. But even that would go against the rest of the
language, since the virtuality would be based on the parameter
type, and not the object on which the function is called. So we
resort to the usual convention of a clone function, e.g.:

Base* Base::clone()
{
Base* result = doClone() ;
assert( typeid( *result ) == typeid( *this ) ) ;
return result ;
}

(doClone(), of course, is a virtual function which must be
overridden in every derived class.)

All of the other cases where I've wanted some dynamic selection
of the type of object being constructed, the selection depended
on some application specific information. This is easily
handled by a map to pointers to a factory (base) class or to a
prototype, but it's hard to see what you could standardize in
the language here, since the information determining the type is
application specific.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,150
Latest member
MakersCBDReviews
Top