Very simple, there are 3 kinds of classes:
1. Abstract classes
2. Base/Derived classes (any derived can also be base)
3. Concrete classes
Diamond inheritance sample explains the first 2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
struct Abstract
{
virtual ~Abstract() = 0;
};
struct Base1 :
virtual public Abstract
{};
struct Base2 :
virtual public Abstract
{};
struct Derived :
public Base1,
public Base2
{
~Derived() {};
};
|
And here is Concrete class
1 2 3 4
|
struct Concrete
{
~Concrete();
}
|
What's the big deal here?
Base and derived classes allow polymorphism, so the base destructor must be either public virtual or protected non virtual.
The purpose of Bases and derivates is that you can inherit from them,
you can call derived from pointer to base.
destruction process is well defined.
You can upcast/downcast and the behavior is well defined on use of the result.
The purpose is also that inheritance allows common behavior for derivates etc. etc.
On the other hand, the purpose of Concrete class is that is acts as "Final" and optionally single class, and thus does not need to provide virtual destructor.
Anyone who would attempt to derive from concrete class is potentially summoning demons to it's code, because concrete classes are not used for this.
As B. Stroustrup says, Concrete classes act as build in types. (you can't override build in type right?) makes no sense.
std::vector
from B. Stroupstrup is perfect example of concrete class.
But that doesn't prevent you from deriving ie. from vector, but you must ensure safety, prevent inheritance of your class and ensure it's not used for polymorphism.
You should also document what' the purpose of your class, how it should be used and how it improves the
std::vector
"build in type" etc.
Quote from B.S. text:
The defining characteristic of a concrete type is that its representation is part
of its definition. |
What means "representation" and what means "definition" and what means that "representation is part of definition"?
representation is what the class represents, and that is it's data members and methods which operate on that data, in the case of std::vector these are single type elements.
Since vector is concrete, it's data and logic is it's implementation.
What that means?
Compared to polymorphics classes the implementation can be in derived classes such as overrided by derivates, but it doesn't have to so 100%. user doesn't know and doesn't need to know this.
Concrete classes do not share it's implementation with derived classes by default, meaning it's implementation is "final" and here in that class, representation and definition are in one class, part of each other, not overriden not shared.