Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Deriving from concrete classes

0 views
Skip to first unread message

Matthias Hofmann

unread,
Jun 20, 2003, 7:05:01 PM6/20/03
to
Hello everyone!

I have recently dealt a lot with a certain aspect of class design:
Wether or
not to derive from concrete classes. I have learned from various books,
articles and newsgroup postings that deriving from concrete classes is
considered a bad idea. A base class should be made abstract, either by
giving it at least one pure virtual function or by making its destructor
protected (and non-virtual).

However, I have to object for two reasons:

1. What is so bad about concrete base classes? The only reason I found
for
not allowing concrete base classes is the problems involved with
assignment.
Since assignment is based on the static type, the derived part of
classes
might no be assigned.

2. Not being able to derive from concrete classes imposes limits that
defeat
the purpose of the language. One of the big advantages of C++ is the
ability
to extend an inheritance hierarchy. If only leaf classes may be
concrete,
than a certain hierarchy and class design is fixed once and forever -
this
makes the possibilities that C++ was designed for go down the drain.

Best regards,

Matthias Hofmann

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

Pete Becker

unread,
Jun 20, 2003, 7:54:23 PM6/20/03
to
Matthias Hofmann wrote:
>
> Wether or
> not to derive from concrete classes. I have learned from various
books,
> articles and newsgroup postings that deriving from concrete classes is
> considered a bad idea.

More accurately, some people regard it as a bad idea.

> A base class should be made abstract, either by
> giving it at least one pure virtual function or by making its
destructor
> protected (and non-virtual).

<shrug>

In some kinds of code that's a good guideline. Be wary of people who
generalize from narrow experience, no matter how deep.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

Sebastian Moleski

unread,
Jun 21, 2003, 6:27:57 AM6/21/03
to
"Matthias Hofmann" <hof...@anvil-soft.com> wrote in message
news:3ef35dab$1...@news.nefonline.de...

> Hello everyone!
>
> I have recently dealt a lot with a certain aspect of class design:
> Wether or
> not to derive from concrete classes. I have learned from various books,
> articles and newsgroup postings that deriving from concrete classes is
> considered a bad idea. A base class should be made abstract, either by
> giving it at least one pure virtual function or by making its destructor
> protected (and non-virtual).

A protected, non-virtual destructor is utterly useless and potentially
dangerous. You need virtual destructors for polymorphism to work right when
deleting an object of a derived class through a pointer to a base class. If
you design a class to be derived from, you must provide a virtual
destructor.

sm

llewelly

unread,
Jun 21, 2003, 6:31:01 AM6/21/03
to
"Matthias Hofmann" <hof...@anvil-soft.com> writes:

> Hello everyone!
>
> I have recently dealt a lot with a certain aspect of class design:
> Wether or
> not to derive from concrete classes. I have learned from various books,
> articles and newsgroup postings that deriving from concrete classes is
> considered a bad idea. A base class should be made abstract, either by
> giving it at least one pure virtual function or by making its destructor
> protected (and non-virtual).

I think you've worded the guideline wrong way around. I'd say: Base
types should usually be abstract, because they are usually categories,
and there's seldom a reason to instantiate categories.

This is an orthodox pure OO notion. If you are using non-OO designs,
you are (more) likely to come across a reason to use concrete
base classes. Much (all?) of the programming advice we encounter
is based on assumptions about styles, tools, and methods. Change
any of those, and the advice may no longer make sense.

> However, I have to object for two reasons:
>
> 1. What is so bad about concrete base classes? The only reason I found
> for
> not allowing concrete base classes is the problems involved with
> assignment.
> Since assignment is based on the static type, the derived part of
> classes
> might no be assigned.

There are really two reasons, that I know of, one design-oriented,
and one technically oriented:

(a) Concrete types typically model 'real' entities. Base types
typically model categories of entities, or attributes common
to many kinds of entities. To use an analogy sword might be
modeled as a concrete type, while weapon might be modeled
as a base type, since weapon is a category. Now, does an object
of type weapon, which is not a sword, spear, rifle,
club, etc, but just some anonymous weapon make sense? Probably
not. This analogy doesn't apply to every problem, or
even every OO problem, but it makes a good guideline.

(b) Implicit conversions. In C++, deriving from a base class
creates 3 kinds of implicit conversions: Derived -> Base,
Derived& -> Base&, and Derived* -> Base* . The first
conversion results in slicing, which you mention, but slicing
doesn't just happen during assignment - it also happens
whenever functions take arguments of base type by value, and
anywhere else objects of base type are copy constructed from
objects of derived type (like catching an exception by value).

IMO, (a) is an important drawback whenever one is designing entity
types using OOP - but I can't see how it applies outside of
OOP. To me, someone who dislikes most implicit conversions,
especially lossy ones, (b) sounds serious - but in practice
assignment and copy by value are often the wrong thing for entity
independent of slicing concerns - so one makes the base class copy
constructor and copy assignment operator private anyway, stopping
the problem. The derived type could declare a private
operator base() conversion function, but I don't know if that's
actually useful.

>
> 2. Not being able to derive from concrete classes imposes limits that
> defeat
> the purpose of the language. One of the big advantages of C++ is the
> ability
> to extend an inheritance hierarchy. If only leaf classes may be
> concrete,
> than a certain hierarchy and class design is fixed once and forever -
> this
> makes the possibilities that C++ was designed for go down the drain.

?

I don't understand this claim. I don't see why one can't derive more
leaf classes from existing abstract base classes in order to
extend the hierarchy.

Francis Glassborow

unread,
Jun 21, 2003, 3:49:18 PM6/21/03
to
In message <vf78k2...@corp.supernews.com>, Sebastian Moleski
<s.mo...@tcu.edu> writes

>A protected, non-virtual destructor is utterly useless and potentially
>dangerous. You need virtual destructors for polymorphism to work right when
>deleting an object of a derived class through a pointer to a base class. If
>you design a class to be derived from, you must provide a virtual
>destructor.


How do you propose to delete a derived object through a base class
pointer if the base has a protected dtor?


--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow ACCU

Ulrich Eckhardt

unread,
Jun 21, 2003, 8:17:15 PM6/21/03
to
Sebastian Moleski wrote:
> A protected, non-virtual destructor is utterly useless and potentially
> dangerous. You need virtual destructors for polymorphism to work right
> when deleting an object of a derived class through a pointer to a base
> class. If you design a class to be derived from, you must provide a
> virtual destructor.

You're misunderstanding something here: you cannot delete an object via a
pointer to the base if the base's destructor is private. The essence of
this boils down to either providing a protected non-virtual or a public
virtual destructor.

I wish I could remember the name of the article that explained this in more
detail, anyone else remembers ?

Ulrich Eckhardt

--
Questions ?
see C++-FAQ Lite: http://parashift.com/c++-faq-lite/ first !

Pete Becker

unread,
Jun 21, 2003, 8:25:02 PM6/21/03
to
Sebastian Moleski wrote:
>
> A protected, non-virtual destructor is utterly useless and potentially
> dangerous. You need virtual destructors for polymorphism to work right when
> deleting an object of a derived class through a pointer to a base class. If
> you design a class to be derived from, you must provide a virtual
> destructor.
>

If your design calls for deleting objects through pointers to the base
then you must make the destructor virtual. There are many uses of
inheritance that do not involve deleting through base pointers.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Matthias Hofmann

unread,
Jun 21, 2003, 8:37:53 PM6/21/03
to

Sebastian Moleski <s.mo...@tcu.edu> schrieb in im Newsbeitrag:
vf78k2...@corp.supernews.com...

> "Matthias Hofmann" <hof...@anvil-soft.com> wrote in message
> news:3ef35dab$1...@news.nefonline.de...
> > Hello everyone!
> >
> > I have recently dealt a lot with a certain aspect of class design:
> > Wether or
> > not to derive from concrete classes. I have learned from various books,
> > articles and newsgroup postings that deriving from concrete classes is
> > considered a bad idea. A base class should be made abstract, either by
> > giving it at least one pure virtual function or by making its
destructor
> > protected (and non-virtual).
>
> A protected, non-virtual destructor is utterly useless and potentially
> dangerous. You need virtual destructors for polymorphism to work right
when
> deleting an object of a derived class through a pointer to a base class.
If
> you design a class to be derived from, you must provide a virtual
> destructor.
>

Well, the point is that if the destructor is protected, you cannot delete a
derived class object through a base class pointer, so there is no danger to
it. You also cannot instantiate an automatic object of that type because the
destructor is inaccesible. This is the reason why many people prefer this
method in order to save the memory for the vtable pointer.

Regards,

Matthias Hofmann

Matthias Hofmann

unread,
Jun 21, 2003, 8:39:17 PM6/21/03
to

llewelly <llewe...@xmission.dot.com> schrieb in im Newsbeitrag:
86fzm4f...@Zorthluthik.local.bar...

> "Matthias Hofmann" <hof...@anvil-soft.com> writes:
>
> >
> > 2. Not being able to derive from concrete classes imposes limits that
> > defeat
> > the purpose of the language. One of the big advantages of C++ is the
> > ability
> > to extend an inheritance hierarchy. If only leaf classes may be
> > concrete,
> > than a certain hierarchy and class design is fixed once and forever -
> > this
> > makes the possibilities that C++ was designed for go down the drain.
>
> ?
>
> I don't understand this claim. I don't see why one can't derive more
> leaf classes from existing abstract base classes in order to
> extend the hierarchy.
>

Well, of course you could derive from an existing abstract class to extend
the hierarchy. But imagine that one of the leaf classes offers almost
exactly what you need, except for a little thing you would just like to add.
In that case, it would be convenient to derive from this concrete class and
just override one of the virtual functions to add this little extra
something. However, if you derive from another abstract class, you have to
implemement everything the concrete class offers yourself.

Of cource you can use a trick: Do not derive from the concrete class, but
implement your class in terms of the concrete one, by containment or even
better by private inheritance (so you can even redefine virtual functions).

Regards,

Matthias

Sebastian Moleski

unread,
Jun 22, 2003, 5:26:44 AM6/22/03
to
"Francis Glassborow" <francis.g...@ntlworld.com> wrote in message
news:NynWonBI...@robinton.demon.co.uk...

> In message <vf78k2...@corp.supernews.com>, Sebastian Moleski
> <s.mo...@tcu.edu> writes
> >A protected, non-virtual destructor is utterly useless and potentially
> >dangerous. You need virtual destructors for polymorphism to work right
when
> >deleting an object of a derived class through a pointer to a base class.
If
> >you design a class to be derived from, you must provide a virtual
> >destructor.
>
>
> How do you propose to delete a derived object through a base class
> pointer if the base has a protected dtor?

You can't. So what is a protected destructor supposed to accomplish anyway?
If it is protected, I have to provide a member function that destroys the
object (e.g. using "delete this;"). The problem with that approach is, of
course, that the object can't be placed on the stack anymore. And if the
class is inteded as a base class, this whole system breaks if the destructor
is protected but still not virtual.

sm

Ulrich Eckhardt

unread,
Jun 22, 2003, 9:04:50 AM6/22/03
to
Sebastian Moleski wrote:

> "Francis Glassborow" <francis.g...@ntlworld.com> wrote:
> > How do you propose to delete a derived object through a base class
> > pointer if the base has a protected dtor?
>
> You can't. So what is a protected destructor supposed to accomplish
> anyway? If it is protected, I have to provide a member function that
> destroys the object (e.g. using "delete this;"). The problem with that
> approach is, of course, that the object can't be placed on the stack
> anymore.

If you call the derived class' dtor, that will in turn call the base's dtor
whan it is finished. No virtual needed. You can perfectly well put such a
beast on the stack, no need to provide any additional memberfunctions or
other hacks.
Note that the derived class does have a public (and sometimes virtual)
dtor.

> And if the class is inteded as a base class, this whole system
> breaks if the destructor is protected but still not virtual.

Being intended as a baseclass doesn't always mean that you're supposed to
store objects of the derived concrete classes via a pointer to the
baseclass. This is especially true if the baseclass only defines an
interface or when you are inheriting some functionality (intrusive
refcounting comes to mind).

Ulrich Eckhardt

--
Questions ?
see C++-FAQ Lite: http://parashift.com/c++-faq-lite/ first !

Francis Glassborow

unread,
Jun 22, 2003, 5:50:20 PM6/22/03
to
In message <3ef4a65d$1...@news.nefonline.de>, Matthias Hofmann
<hof...@anvil-soft.com> writes

>Of cource you can use a trick: Do not derive from the concrete class,
but
>implement your class in terms of the concrete one, by containment or
even
>better by private inheritance (so you can even redefine virtual
functions).

However be aware that there are some problems with using either private
inheritance if dynamic_casting might be used.

--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow ACCU

Francis Glassborow

unread,
Jun 22, 2003, 5:51:30 PM6/22/03
to
In message <vf9ncuo...@corp.supernews.com>, Sebastian Moleski
<seb...@yahoo.com> writes

> > How do you propose to delete a derived object through a base class
> > pointer if the base has a protected dtor?
>
>You can't. So what is a protected destructor supposed to accomplish
anyway?
>If it is protected, I have to provide a member function that destroys
the
>object (e.g. using "delete this;"). The problem with that approach is,
of
>course, that the object can't be placed on the stack anymore. And if
the
>class is inteded as a base class, this whole system breaks if the
destructor
>is protected but still not virtual.

Learning about the idioms in common use in some programming domains
might help make it clear what they are good for.

protected/private dtors are deliberately used where stack based
instances would be an error. Windows type frameworks often have this
requirement, as do some cases for use with COM and CORBA

They are also used where any freestanding instance would be a mistake.
This is also a frequent idiom in COM and CORBA exactly because it saves
creating a vtable when one is not wanted.

The use of a protected/private dtor accomplishes two things

1) it prevents the creation of auto objects of that type
2) it prevents deleting derived object through a pointer to this type.

Those things are independently useful in some designs.


--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow ACCU

James Kanze

unread,
Jun 22, 2003, 5:53:25 PM6/22/03
to
Pete Becker <peteb...@acm.org> writes:

|> Matthias Hofmann wrote:

|> > Wether or not to derive from concrete classes. I have learned
|> > from various books, articles and newsgroup postings that
|> > deriving from concrete classes is considered a bad idea.

|> More accurately, some people regard it as a bad idea.

Most accurately, some people regard it as a bad idea in certain
circomstances. It's a bad idea often enough that if you find yourself
doing it, it's worth asking why. But if the reasons are valid...

--
James Kanze mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France Tel. +33 1 41 89 80 93

James Kanze

unread,
Jun 22, 2003, 5:53:47 PM6/22/03
to
"Sebastian Moleski" <seb...@yahoo.com> writes:

|> "Francis Glassborow" <francis.g...@ntlworld.com> wrote in
message
|> news:NynWonBI...@robinton.demon.co.uk...
|> > In message <vf78k2...@corp.supernews.com>, Sebastian Moleski
|> > <s.mo...@tcu.edu> writes
|> > >A protected, non-virtual destructor is utterly useless and
|> > >potentially dangerous. You need virtual destructors for
|> > >polymorphism to work right when deleting an object of a
|> > >derived class through a pointer to a base class. |> If you
|> > >design a class to be derived from, you must provide a virtual
|> > >destructor.

|> > How do you propose to delete a derived object through a base
|> > class pointer if the base has a protected dtor?

|> You can't. So what is a protected destructor supposed to
|> accomplish anyway?

Prevents deletion through a pointer to the base class. In other
words, prevents undefined behavior.

--
James Kanze mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France Tel. +33 1 41 89 80 93

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

James Kanze

unread,
Jun 22, 2003, 5:54:12 PM6/22/03
to
Ulrich Eckhardt <doom...@knuut.de> writes:

|> Sebastian Moleski wrote:
|> > A protected, non-virtual destructor is utterly useless and
|> > potentially dangerous. You need virtual destructors for
|> > polymorphism to work right when deleting an object of a derived
|> > class through a pointer to a base class. If you design a class
|> > to be derived from, you must provide a virtual destructor.

|> You're misunderstanding something here: you cannot delete an
|> object via a pointer to the base if the base's destructor is
|> private.

You can't derive from the class if the destructor is private.

--
James Kanze mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France Tel. +33 1 41 89 80 93

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Terje Slettebø

unread,
Jun 22, 2003, 8:07:36 PM6/22/03
to
"Ulrich Eckhardt" <doom...@knuut.de> wrote in message
news:bd1vc8$nhc0g$1...@ID-178288.news.dfncis.de...

> Sebastian Moleski wrote:
> > A protected, non-virtual destructor is utterly useless and
potentially
> > dangerous. You need virtual destructors for polymorphism to work
right
> > when deleting an object of a derived class through a pointer to a
base
> > class. If you design a class to be derived from, you must provide a
> > virtual destructor.
>
> You're misunderstanding something here: you cannot delete an object
via a
> pointer to the base if the base's destructor is private. The essence
of
> this boils down to either providing a protected non-virtual or a
public
> virtual destructor.
>
> I wish I could remember the name of the article that explained this in
more
> detail, anyone else remembers ?

"Virtuality" by Herb Sutter
(http://www.gotw.ca/publications/mill18.htm):

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

This is a recurring theme, and again and again we get postings saying
you need a virtual destructor for a base class, when that doesn't need
to be the case, and there are safe, efficient alternatives, such as
protected nonvirtual destructors.


Regards,

Terje

Matthias Hofmann

unread,
Jun 22, 2003, 8:08:19 PM6/22/03
to

Ulrich Eckhardt <doom...@knuut.de> schrieb in im Newsbeitrag:
bd1vc8$nhc0g$1...@ID-178288.news.dfncis.de...

>
> I wish I could remember the name of the article that explained this in
more
> detail, anyone else remembers ?
>
> Ulrich Eckhardt
>

I don't know if this it what you are looking for, but some information
on
this topic can be found here:

http://www.gotw.ca/publications/mill18.htm

Best regards,

Matthias Hofmann

Terje Slettebø

unread,
Jun 22, 2003, 8:10:14 PM6/22/03
to
"Matthias Hofmann" <hof...@anvil-soft.com> wrote in message
news:3ef4a65d$1...@news.nefonline.de...

>
> llewelly <llewe...@xmission.dot.com> schrieb in im Newsbeitrag:
> 86fzm4f...@Zorthluthik.local.bar...
> > "Matthias Hofmann" <hof...@anvil-soft.com> writes:
> >
> > >
> > > 2. Not being able to derive from concrete classes imposes limits
that
> > > defeat
> > > the purpose of the language. One of the big advantages of C++ is
the
> > > ability
> > > to extend an inheritance hierarchy. If only leaf classes may be
> > > concrete,
> > > than a certain hierarchy and class design is fixed once and
forever -
> > > this
> > > makes the possibilities that C++ was designed for go down the
drain.

On the contrary. As has been said in this thread, a concrete base class
serves two roles: As an interface, and as an implementation of that
interface. It may make a more cohesive design to separate the roles. As
it says in the "Effective C++" books, then you identify the abstraction
that is common, and make an abstract/non-instantiable base class of it.

An apparently common misconception when it comes to OO is that you can
take any class and derive from it to make a new class. However, classes
typically need to be designed to be derived from. A class presents two
interfaces to the world: The public interface, for all, and the public
and protected interface, for any derived classes. If the class is not
designed with inheritance in mind, its interface for derived classes is
essentially random, and therefore not likely to be appropriate.


Regards,

Terje

Herb Sutter

unread,
Jun 23, 2003, 6:02:59 AM6/23/03
to
On 22 Jun 2003 17:53:47 -0400, James Kanze <ka...@alex.gabi-soft.fr>
wrote:

>|> > How do you propose to delete a derived object through a base
>|> > class pointer if the base has a protected dtor?
>
>|> You can't. So what is a protected destructor supposed to
>|> accomplish anyway?

The above question was itself the answer: A protected destructor expresses
that deletion is not one of the operations you can do through the base
interface. It can make sense to support other virtual operations and not
deletion (e.g., when a framework owns the objects, or in a
garbage-collected system where the objects are designed to clean
themselves up at finalization time, which is sometime after the last
pointer to the object has been let go).

As James put it:


>Prevents deletion through a pointer to the base class. In other
>words, prevents undefined behavior.

For more on this, see also my article:

"Virtuality"
C/C++ Users Journal, 19(9), September 2001
http://www.gotw.ca/publications/mill18.htm

Quoting from the Summary:

"For the special case of the destructor only:
- Guideline #4: A base class destructor should be either


public and virtual, or protected and nonvirtual."

Herb

---
Herb Sutter (www.gotw.ca)

Convener, ISO WG21 (C++ standards committee) (www.gotw.ca/iso)
Contributing editor, C/C++ Users Journal (www.gotw.ca/cuj)
Visual C++ program manager, Microsoft (www.gotw.ca/microsoft)

llewelly

unread,
Jun 23, 2003, 11:49:18 AM6/23/03
to
Francis Glassborow <francis.g...@ntlworld.com> writes:

> In message <3ef4a65d$1...@news.nefonline.de>, Matthias Hofmann
> <hof...@anvil-soft.com> writes
>>Of cource you can use a trick: Do not derive from the concrete class,
> but
>>implement your class in terms of the concrete one, by containment or
> even
>>better by private inheritance (so you can even redefine virtual
> functions).
>
> However be aware that there are some problems with using either
private
> inheritance if dynamic_casting might be used.

[snip]

Could you explain what these problems are?

Matthias Hofmann

unread,
Jun 23, 2003, 3:20:25 PM6/23/03
to

Francis Glassborow <francis.g...@ntlworld.com> schrieb in im
Newsbeitrag: LzPHo9Ap...@robinton.demon.co.uk...

> In message <3ef4a65d$1...@news.nefonline.de>, Matthias Hofmann
> <hof...@anvil-soft.com> writes
> >Of cource you can use a trick: Do not derive from the concrete class,
> but
> >implement your class in terms of the concrete one, by containment or
> even
> >better by private inheritance (so you can even redefine virtual
> functions).
>
> However be aware that there are some problems with using either private
> inheritance if dynamic_casting might be used.
>

What are these problems? As far as I know, private inheritance simply means
(among other things) that you cannot convert a
pointer-to-derived-class-object to a pointer-to-base-class-object.

Regards,

Matthias

Matthias Hofmann

unread,
Jun 23, 2003, 3:21:07 PM6/23/03
to

Terje Slettebø <tsle...@chello.no.nospam> schrieb in im Newsbeitrag:
sykJa.13131$KF1.276359@amstwist00...

> "Matthias Hofmann" <hof...@anvil-soft.com> wrote in message
> news:3ef4a65d$1...@news.nefonline.de...
> >
> > llewelly <llewe...@xmission.dot.com> schrieb in im Newsbeitrag:
> > 86fzm4f...@Zorthluthik.local.bar...
> > > "Matthias Hofmann" <hof...@anvil-soft.com> writes:
> > >
> > > >
> > > > 2. Not being able to derive from concrete classes imposes limits
> that
> > > > defeat
> > > > the purpose of the language. One of the big advantages of C++ is
> the
> > > > ability
> > > > to extend an inheritance hierarchy. If only leaf classes may be
> > > > concrete,
> > > > than a certain hierarchy and class design is fixed once and
> forever -
> > > > this
> > > > makes the possibilities that C++ was designed for go down the
> drain.
>
> On the contrary. As has been said in this thread, a concrete base class
> serves two roles: As an interface, and as an implementation of that
> interface. It may make a more cohesive design to separate the roles. As
> it says in the "Effective C++" books, then you identify the abstraction
> that is common, and make an abstract/non-instantiable base class of it.

I understand that an abstract base class makes sense as it provides an
interface. The one thing that confused me a little was just the idea of a
concrete class being the end of an inheritance-path.

>
> An apparently common misconception when it comes to OO is that you can
> take any class and derive from it to make a new class. However, classes
> typically need to be designed to be derived from. A class presents two
> interfaces to the world: The public interface, for all, and the public
> and protected interface, for any derived classes. If the class is not
> designed with inheritance in mind, its interface for derived classes is
> essentially random, and therefore not likely to be appropriate.
>
>

"...and the public and protected interface, for any derived classes." - I
guess one has to add private virtual functions to this list.

So one can generally say:

"If the class is abstract, derive from it if you like. If it is concrete,
please don't."

Is that a good guideline?

Regards,

Matthias

ka...@gabi-soft.fr

unread,
Jun 23, 2003, 3:21:49 PM6/23/03
to
Terje Slettebø <tsle...@chello.no.nospam> wrote in message
news:<sykJa.13131$KF1.276359@amstwist00>...

> "Matthias Hofmann" <hof...@anvil-soft.com> wrote in message
> news:3ef4a65d$1...@news.nefonline.de...

> > llewelly <llewe...@xmission.dot.com> schrieb in im Newsbeitrag:
> > 86fzm4f...@Zorthluthik.local.bar...
> > > "Matthias Hofmann" <hof...@anvil-soft.com> writes:

> > > > 2. Not being able to derive from concrete classes imposes
> > > > limits that defeat the purpose of the language. One of the big
> > > > advantages of C++ is the ability to extend an inheritance
> > > > hierarchy. If only leaf classes may be concrete, than a certain
> > > > hierarchy and class design is fixed once and forever - this
> > > > makes the possibilities that C++ was designed for go down the
> > > > drain.

> On the contrary. As has been said in this thread, a concrete base
> class serves two roles: As an interface, and as an implementation of
> that interface. It may make a more cohesive design to separate the
> roles. As it says in the "Effective C++" books, then you identify the
> abstraction that is common, and make an abstract/non-instantiable base
> class of it.

You're supposing that the only role of a base class should be an
interface. I agree that it is the most frequent pattern, but, for
example, what about an implementation of the template pattern when you
have a very good default implementation.

> An apparently common misconception when it comes to OO is that you can
> take any class and derive from it to make a new class. However,
> classes typically need to be designed to be derived from. A class
> presents two interfaces to the world: The public interface, for all,
> and the public and protected interface, for any derived classes. If
> the class is not designed with inheritance in mind, its interface for
> derived classes is essentially random, and therefore not likely to be
> appropriate.

Again: what about the template pattern. The base class has a concrete
implementation, which can be customized in one or a few very constrained
ways; customization is through derivation. If you have reasonable
defaults for all of the customizations, for example, what is the problem
with providing them? And if you provide them, the base class becomes
concrete. It's not a particularly frequent pattern, at least in my
code, but I certainly wouldn't want to see it banned, either, on the
grounds that it involves inheriting from a concrete class.

--
James Kanze GABI Software mailto:ka...@gabi-soft.fr


Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung

11 rue de Rambouillet, 78460 Chevreuse, France, Tél. : +33 (0)1 30 23 45 16

Francis Glassborow

unread,
Jun 23, 2003, 3:40:21 PM6/23/03
to
In message <86vfux4...@Zorthluthik.local.bar>, llewelly
<llewe...@xmission.dot.com> writes

>Francis Glassborow <francis.g...@ntlworld.com> writes:
>
>> In message <3ef4a65d$1...@news.nefonline.de>, Matthias Hofmann
>> <hof...@anvil-soft.com> writes
>>>Of cource you can use a trick: Do not derive from the concrete class,
>> but
>>>implement your class in terms of the concrete one, by containment or
>> even
>>>better by private inheritance (so you can even redefine virtual
>> functions).
>>
>> However be aware that there are some problems with using either
>private
>> inheritance if dynamic_casting might be used.
>[snip]
>
>Could you explain what these problems are?

Try dynamic casting when private inheritance is involved. IIRC a private
base acts as a block to a dynamic cast. But do not take my word for it.


--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow ACCU

Peter Dimov

unread,
Jun 25, 2003, 4:30:27 PM6/25/03
to
ka...@gabi-soft.fr wrote in message news:<d6652001.03062...@posting.google.com>...

>
> Again: what about the template pattern. The base class has a concrete
> implementation, which can be customized in one or a few very constrained
> ways; customization is through derivation. If you have reasonable
> defaults for all of the customizations, for example, what is the problem
> with providing them? And if you provide them, the base class becomes
> concrete. It's not a particularly frequent pattern, at least in my
> code, but I certainly wouldn't want to see it banned, either, on the
> grounds that it involves inheriting from a concrete class.

It is much easier to explain inheritance from an abstract base: you
should inherit if and only if your class needs to implement the
interface represented by the abstract base.

Inheritance from a concrete class is much harder to explain or
justify; an inexperienced programmer can't easily tell the good uses
from the bad, and an experienced programmer sometimes needs to look
several moves ahead to foresee the potential problems.

So I'd leave the virtual functions pure in your example, even if I had
good defaults. Of course this has its drawbacks, too. :-)

Peter Dimov

unread,
Jun 25, 2003, 4:49:02 PM6/25/03
to
"Sebastian Moleski" <seb...@yahoo.com> wrote in message news:<vf9ncuo...@corp.supernews.com>...

> "Francis Glassborow" <francis.g...@ntlworld.com> wrote in message
> news:NynWonBI...@robinton.demon.co.uk...
> > In message <vf78k2...@corp.supernews.com>, Sebastian Moleski
> > <s.mo...@tcu.edu> writes
> > >A protected, non-virtual destructor is utterly useless and potentially
> > >dangerous. You need virtual destructors for polymorphism to work right
> when
> > >deleting an object of a derived class through a pointer to a base class.
> If
> > >you design a class to be derived from, you must provide a virtual
> > >destructor.
> >
> >
> > How do you propose to delete a derived object through a base class
> > pointer if the base has a protected dtor?
>
> You can't. So what is a protected destructor supposed to accomplish anyway?

An abstract class usually represents an interface that specifies the
operations that can be performed via a pointer to this interface.

struct X
{
virtual void f() = 0;
};

says that if I have a pointer p to X, I can call p->f().

Whether 'delete p' is an acceptable operation is typically signalled
by the presence of a public virtual destructor in the interface:

struct Y
{
virtual ~Y() {}
virtual void g() = 0;
};

So I am (logically) allowed to delete an Y, but not an X.

Unfortunately, even though ~X is not explicitly present, it is still
public, so the user can (physically) delete a pointer to X. A
protected destructor closes this loophole, bringing the logical and
the physical interface in sync:

struct X
{
virtual void f() = 0;

protected:
~X() {}
};

boost::shared_ptr<X> supports this idiom and will not attempt to
invoke the protected destructor when initialized with a pointer to a
class derived from X.

Siemel Naran

unread,
Jun 26, 2003, 10:09:30 AM6/26/03
to
"Matthias Hofmann" <hof...@anvil-soft.com> wrote in message

> Well, of course you could derive from an existing abstract class to


extend
> the hierarchy. But imagine that one of the leaf classes offers almost
> exactly what you need, except for a little thing you would just like
to
add.
> In that case, it would be convenient to derive from this concrete
class
and
> just override one of the virtual functions to add this little extra
> something. However, if you derive from another abstract class, you
have to
> implemement everything the concrete class offers yourself.

In my experience, a very compelling argument to ignore the rule that we
ought to derive only from abstract classes.

Sometimes, several virtual functions are related, and if we override one
we
should override all of them. If we derive from concrete classes there
is a
possibility we may forget to override some virtual functions. However,
perhaps this problem is better solved through either: reading the
documentation, writing an extensive test driver, factoring the code so
that
there is only one function to override (not a whole group of functions).


> Of cource you can use a trick: Do not derive from the concrete class,
but
> implement your class in terms of the concrete one, by containment or
even
> better by private inheritance (so you can even redefine virtual
functions).

Not recommended. Too much typing, plus the implicit conversion problem
Francis pointed out.


--
+++++++++++
Siemel Naran

Siemel Naran

unread,
Jun 26, 2003, 10:23:28 AM6/26/03
to
"Matthias Hofmann" <hof...@anvil-soft.com> wrote in message

> Well, of course you could derive from an existing abstract class to


extend
> the hierarchy. But imagine that one of the leaf classes offers almost
> exactly what you need, except for a little thing you would just like
to
add.
> In that case, it would be convenient to derive from this concrete
class
and
> just override one of the virtual functions to add this little extra
> something. However, if you derive from another abstract class, you
have to
> implemement everything the concrete class offers yourself.

In my experience, a very compelling argument to ignore the rule that we


ought to derive only from abstract classes.

Sometimes, several virtual functions are related, and if we override one
we
should override all of them. If we derive from concrete classes there
is a
possibility we may forget to override some virtual functions. However,
perhaps this problem is better solved through either: reading the
documentation, writing an extensive test driver, factoring the code so
that
there is only one function to override (not a whole group of functions).

> Of cource you can use a trick: Do not derive from the concrete class,
but
> implement your class in terms of the concrete one, by containment or
even
> better by private inheritance (so you can even redefine virtual
functions).

Not recommended. Too much typing, plus the implicit conversion problem
Francis pointed out.


--
+++++++++++
Siemel Naran

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

ka...@gabi-soft.fr

unread,
Jun 26, 2003, 3:10:14 PM6/26/03
to
pdi...@mmltd.net (Peter Dimov) wrote in message
news:<7dc3b1ea.03062...@posting.google.com>...

I would certainly teach inhertance starting with abstract base classes.
But I don't work in a school; I expect my collegues to already know what
inheritance is, and to be familiar with the concept of interfaces.

For the rest, I've found that a reference to the design pattern has
generally been sufficient. No one in the places I've worked would dare
admit to not being familiar with the design patterns in the Gang of
Four's book:-).

On the other hand, the case is relatively rare. Generally speaking, in
my more recent work, I will use delegates rather than the template
pattern. So the issue doesn't come up that often. (And I can't think
of any other case off hand where you might want to inherit from a
concrete class.)

--
James Kanze GABI Software
mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter
Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, Tél. : +33 (0)1 30 23 45
16

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Peter Dimov

unread,
Jun 27, 2003, 10:07:07 AM6/27/03
to
ka...@gabi-soft.fr wrote in message news:<d6652001.03062...@posting.google.com>...
> pdi...@mmltd.net (Peter Dimov) wrote in message
> news:<7dc3b1ea.03062...@posting.google.com>...
>
> > So I'd leave the virtual functions pure in your example, even if I had
> > good defaults. Of course this has its drawbacks, too. :-)
>
> I would certainly teach inhertance starting with abstract base classes.
> But I don't work in a school; I expect my collegues to already know what
> inheritance is, and to be familiar with the concept of interfaces.

I have (empirically) found that actively avoiding inheritance from
concrete classes pays off regardless of skill. It often leads to
better designs, but that aside, one very practical reason for the
guideline is that C++ doesn't have "override" to help prevent mistakes
like:

struct X
{
virtual void f() const;
};

struct Y: X
{
virtual void f();
};

where Y::f is intended to override X::f but does not.

Siemel Naran

unread,
Jun 28, 2003, 7:11:31 PM6/28/03
to
"Peter Dimov" <pdi...@mmltd.net> wrote in message

> I have (empirically) found that actively avoiding inheritance from
> concrete classes pays off regardless of skill. It often leads to
> better designs, but that aside, one very practical reason for the

Why? Can you elaborate?

--
+++++++++++
Siemel Naran

0 new messages