On pure abstract classes

M

Miguel Guedes

Hello,

I recently read an interview [1] with Bjarne Stroustrup in which he says
that pure abstract classes should *not* contain any data. However, I
have found that at times situations are when it would be useful to have
/some/ data defined in such an abstract class for reasons of forming a
common block of data existing in or used by all descendant classes (see
example below.) In such a case where a common block of data *always*
exists, can data be incorporated into a pure abstract class without good
programming and C++ design practices being violated?

Secondly, can enums be defined in abstract classes or is this not a good
practice?

Thank you.


[1] http://www.artima.com/intv/modern.html

-----------------------------------------
Example:

class Base
{
..
:
..
protected:
virtual bool IsEnabled()
{ return _enabled; }

virtual PureAbstract() = 0;

protected:
bool _enabled;
};
 
V

Victor Bazarov

Miguel said:
I recently read an interview [1] with Bjarne Stroustrup in which he
says that pure abstract classes should *not* contain any data.

I cannot find those exact words. Care to point out the specific
passage?
However, I have found that at times situations are when it would be
useful to have /some/ data defined in such an abstract class for
reasons of forming a common block of data existing in or used by all
descendant classes (see example below.) In such a case where a common
block of data *always* exists, can data be incorporated into a pure
abstract class without good programming and C++ design practices
being violated?

Sure. "Should" doesn't mean "shall", even from Dr Stroustrup himself.

If your model calls for it, use it.
Secondly, can enums be defined in abstract classes or is this not a
good practice?

How do you define "good"? Enums are usually part of interface. They
in that case *definitely* belong in a base class.
Thank you.


[1] http://www.artima.com/intv/modern.html

-----------------------------------------
Example:

class Base
{
..
protected:
virtual bool IsEnabled()
{ return _enabled; }

virtual PureAbstract() = 0;

virtual *sometype* PureAbstract() = 0;
protected:
bool _enabled;
};

V
 
M

Miguel Guedes

Victor,

Thank you for your reply. I must say I am a bit confused and unsure how
to design and implement abstract classes. Hopefully you can shed some
light on this for me. For your time and consideration, I thank you.
I cannot find those exact words. Care to point out the specific
passage?

First of all he starts by stating in page 1 that "from a C++ view
there's no difference between an abstract class and an interface" (you
use the term /interface/ in your reply) and that a "pure abstract class
(...) exclusively has pure virtual functions (and no data)." He also
mentions that since 1987 he has "consistently pointed out that one of
the major ways of writing classes in C++ is without any state, that is,
just an interface." All of this is said, as I understood it, in the
context of multiple inheritance and how it can be avoided in most cases
by deploying interfaces.

However, I also think he meant what he said from a more generic point of
view, as in how interfaces /should/ be designed, that being, stateless.
And I tend to believe what this great man preaches, for obvious reasons.

Do you agree with this design philosophy? Are there any benefits in
terms of how efficient and optimized the compiler generates code when
abstract classes are designed in accordance to this 'convention'?
Sure. "Should" doesn't mean "shall", even from Dr Stroustrup himself.

I understand that /should/ doesn't necessarily mean /shall/, so much so
that the compiler (VS, in my case) lets me incorporate data in
interfaces without generating any L3 warnings whatsoever, however if
/should/ means better design philosophy and possibly more efficient and
optimized code I'd personally stick to that.

In addition, another reason why I'm so unsure is I've been faced with
situations where a common block of data exists that could be put in an
interface class and, to have to not only repeat the same data in all of
the descendant classes but also repeat code in similar methods (an
interface exclusively has pure virtual functions), doesn't seem to make
much sense to me...

Your comments will be greatly appreciated.

Miguel
 
J

James Kanze

Thank you for your reply. I must say I am a bit confused and
unsure how to design and implement abstract classes.

It depends on the role of the abstract class. In the template
method pattern, the base class is abstract, but it will not
follow the same rules as an interface (which is also abstract).
Hopefully you can shed some light on this for me. For your
time and consideration, I thank you.
First of all he starts by stating in page 1 that "from a C++ view
there's no difference between an abstract class and an interface" (you
use the term /interface/ in your reply) and that a "pure abstract class
(...) exclusively has pure virtual functions (and no data)."

In other words, he's defining what he means when he says that a
class is "pure abstract". (Note that the language itself
doesn't have this concept.) He's not saying that a "pure
abstract class should have no data members", he's saying that if
a class has data members, it isn't what he is calling "pure
abstract".

Note that he's taking pains here to separate out a subset of the
abstract classes. He's explicitly not talking about the base
class in the template method pattern, for example.
He also
mentions that since 1987 he has "consistently pointed out that one of
the major ways of writing classes in C++ is without any state, that is,
just an interface." All of this is said, as I understood it, in the
context of multiple inheritance and how it can be avoided in most cases
by deploying interfaces.

I'm not sure of the relationship with multiple inheritance, but
"interfaces" do go back a long way in C++. Perhaps the reason
he introduces the term "pure abstract classes" is that too many
people confuse "interface" with the Java keyword, and forget
that it was a concept of C++ design long before Java ever
existed. (And perhaps the relationship with multiple
inheritance is simply that a class without data members never
needs anything but a default constructor. When multiple
inheritance is involved, you frequently need virtual
inheritance. Virtual inheritance means that the most derived
class must call the constructor, and if it has to provide
arguments, that can be a problem at times.)
However, I also think he meant what he said from a more generic point of
view, as in how interfaces /should/ be designed, that being, stateless.
And I tend to believe what this great man preaches, for obvious reasons.

It's a question of definition. An interface is stateless. If a
class has state, it's not an interface.

I'd be very surprised if Stroustrup said that it's a mortal sin
to design an abstract class which isn't an interface (or which
isn't a pure abstract class). I'm sure he's familiar with the
template method pattern, from a time long before it acquired
that name. And he's very much not the person to say that
because A is a good solution for B, using C to solve D is wrong.

If you need to provide an abstract interface, then defining a
class with only pure virtual functions and no data members is an
excellent solution in C++. If you need to do something else,
then it's quite possible that some other solution is
appropriate.
Do you agree with this design philosophy? Are there any benefits in
terms of how efficient and optimized the compiler generates code when
abstract classes are designed in accordance to this 'convention'?

It has nothing (or very littel) to do with how a compiler
generates code. It has to do with how you understand something.
I understand that /should/ doesn't necessarily mean /shall/, so much so
that the compiler (VS, in my case) lets me incorporate data in
interfaces without generating any L3 warnings whatsoever,

Woah. You can't possibly incorporate data in an interface,
because if you do, it isn't an interface. The language doesn't
have a specific concept of "interface", however, and there's no
way to tell the compiler that a particular class definition is
an interface, and that incorporating data in it would be an
error.
however if /should/ means better design philosophy and
possibly more efficient and optimized code I'd personally
stick to that.
In addition, another reason why I'm so unsure is I've been
faced with situations where a common block of data exists that
could be put in an interface class and, to have to not only
repeat the same data in all of the descendant classes but also
repeat code in similar methods (an interface exclusively has
pure virtual functions), doesn't seem to make much sense to
me...

One pattern that I've encountered from time to time is to use
the template method pattern to implement an interface. This
results in a three level hierarchy: the interface (with no
data), the template method base (has data, and implements the
functions in the interface, but introduces new pure virtual
functions of its own), and the final derived class.
Alternatively, you can introduce a "helper" class between the
interface and the implementation, with common data and
functionality. (Typically, all of the functions in the helper
class will be protected. In many cases, it's even logical for
the data to be protected, something that I would strongly
recommend against in most cases.)
 
D

Duane

Miguel Guedes said:
Victor,

Thank you for your reply. I must say I am a bit confused and unsure how
to design and implement abstract classes. Hopefully you can shed some
light on this for me. For your time and consideration, I thank you.

An abstract class is a class with a pure abstract function. How you
implement it depends a lot on which design you're using. Maybe
you want to do some reading wrt design patterns.
 
M

Milburn Young

Hello,

I recently read an interview [1] with Bjarne Stroustrup in which he says
that pure abstract classes should *not* contain any data. However, I
have found that at times situations are when it would be useful to have
/some/ data defined in such an abstract class for reasons of forming a
common block of data existing in or used by all descendant classes (see
example below.) In such a case where a common block of data *always*
exists, can data be incorporated into a pure abstract class without good
programming and C++ design practices being violated?

Secondly, can enums be defined in abstract classes or is this not a good
practice?

Thank you.

[1]http://www.artima.com/intv/modern.html

-----------------------------------------
Example:

class Base
{
.
:
.
protected:
virtual bool IsEnabled()
{ return _enabled; }

virtual PureAbstract() = 0;

protected:
bool _enabled;

};

Miguel, I think you might mean "pure virtual", not "pure abstract".
To my understanding, an abstract class is a class that _does_ define
_both_ virtual and non-virtual data members and/or methods. I find
abstract classes just as useful as pure virtual interfaces. The
trouble I often run into is what is called "covariance". You have a
virtual method in the base class that returns a reference to its own
type. The method has to be overridden in the derived class, but you
want each derived class to return a reference to its own type (which
the base class knows nothing about). Some compilers don't support
this. The workaround is the CRTP (Curiously Recurring Template
Pattern) where you pass the newly derived class as a template argument
to the base class; however, now you have to compensate for Foo<A> is
not the same type as Foo<B>. Over time, you will discover the
benefits of each and know which to use when.

As far as enums go, I think you can specify enums in a class and it
still be pure virtual because enums are not handled the same as other
members. Fill an otherwise empty class/struct with some enums and get
a sizeof it and you'll see what I mean. I only use them if I give the
enum a name or put them inside a nested struct and never use them as
integral types because not all compilers like to go back-and-forth
between enum and int. Maybe one day enums will have compile-time
bounds checking and be a proper type qualifier like class and
struct...

Milburn Young
 
J

James Kanze

On Jul 16, 5:27 pm, Miguel Guedes <[email protected]> wrote:

[...]
Miguel, I think you might mean "pure virtual", not "pure abstract".
To my understanding, an abstract class is a class that _does_ define
_both_ virtual and non-virtual data members and/or methods.

An abstract class, in C++, is a class that has one or more pure
virtual functions. It may have anything else, but it needn't.
From a design point of view (rather than a language point of
view), the definition probably depends on the design methodology
being used.

[...]
As far as enums go, I think you can specify enums in a class and it
still be pure virtual because enums are not handled the same as other
members.

In what way?

A class cannot be pure virtual; only functions can be pure
virtual. And enums are handled exactly like any other type in
C++.
Fill an otherwise empty class/struct with some enums and get
a sizeof it and you'll see what I mean.

What do you mean?
I only use them if I give the
enum a name or put them inside a nested struct and never use them as
integral types because not all compilers like to go back-and-forth
between enum and int.

Enum to int should always work. Int to enum requires an
explicit type conversion.
Maybe one day enums will have compile-time
bounds checking and be a proper type qualifier like class and
struct...

An enum is a proper type in C++. It isn't a proper enumeration
type, but that's another issue---C++ doesn't have a proper
enumeration type. Nor a proper subrange type, nor a few other
odds and ends. (Luckily nothing too important, other than a
null pointer constant that isn't an int.)
 

nmi

Joined
Jul 6, 2007
Messages
13
Reaction score
0
Miguel Guedes said:
Hello,

I recently read an interview [1] with Bjarne Stroustrup in which he says
that pure abstract classes should *not* contain any data. However, I
have found that at times situations are when it would be useful to have
/some/ data defined in such an abstract class for reasons of forming a
common block of data existing in or used by all descendant classes (see
example below.)

I think that it is generally a bit dangerous using base-class data in a derived class; whether the base class is abstract or not is beside the point.

Whenever you use inherited data you are at the mercy of the base class author. At some point in the future he may be changing those data in a way that lets you compile your derived class but causes a runtime crash. The base class author may be totally unaware of the existence of your derived class!

Actually the situation is nearly the same as using data from an unrelated class - encapsulation is broken.
 
Last edited:

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,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top