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.)