In Bjarne Stroustrup’s book “The C++ Programming Language”, it is stated that a derived class from a super class in a class hierarchy, in many case, gets access to the data of the super class. The book suggests this is a problem, because the sharing between “two related, but different, sets of data is asking for trouble. Sooner or later someone will get them out of sync. Also, experience shows that novice programmers tend to mess with protected data in ways that are unnecessary and that cause maintenance problems“. The question here is, how can having access to private data from the ancestor class is asking for trouble? It sounds like having inherited assets from your parent is a bad deal.
As a consequence, the pure abstract class mechanism allows the separation between the abstract class and its implementation. Note that the implementation includes data members, because if the data members are defined in an abstract class, the abstract class contains implementation details (the defined members), thus it is not well decoupled between abstraction and the implementation. Why is such separation needed? One of the reason, as stated in here, is “a way of forcing a contract between the class designer and the users of that class. The users of this class must declare a matching member function for the class to compile.” Another important reason, as stated in the book, is to protect against changes from the implementation. Having an abstract class hierarchy, you can protect against the changes which requires compilation of an entire class hierarchy.
For example, if you have a normal class, and the class contains 10 data members and 20 member functions, and is inherited by a dozen of classes with several layers below the root class. A few changes to the implementation of member functions (function signature remains unchanged) of the root class, and you have to recompile the entire class hierarchy to apply changes its terminal classes, otherwise the program breaks. With abstract class hierarchy, unless the function signature is changed, if an implementation of a terminal class changes, only that terminal class needs to be recompiled. Therefore, most of the code are protected to the maximum. Is my understanding correct?
I think his example (the Ival_box example) in combination with the Bridge Design Pattern tries, and is powerful, since Bridge Pattern leaves the abstract tree completely, and have another class hierarchy for implementation. Pure abstract class can be consider equivalent to Interface in Java, except in Java the explanation usually is the abstract class can be inherited once, while interface allow multiple inheritances, thus having shared behaviors encapsulated in a shared interface between multiple classes. That answer, I think, is not valid in this context, since C++ allows multiple inheritance.
The last question is, how is a derived class compiled and exist in the binary image? Does the compiler fill the inherited information into the derived class, considered it to be an isolated class afterward and then compiled? (Similar to preprocessing)
tl;dr:
How can having access to private data from the ancestor class is asking for trouble?
Is pure abstract class (aka Interface in Java) a way to protect source code against changes, with the separation of abstraction tree and implementation tree?
How is abstract class/super class compiled in C++? Does it turn the derived class into a single class by filling in the information from superclass, then compiles
Meta-note: Your questions could have been asked as multiple, separate questions.
Non-orthogonality. When the protected part of the ancestor class is changed, all derived classes have to be changed, too. This is error-prone, because the programmer changing the ancestor might not have the derived classes in his mental scope.
Technically correct, but you are missing the main point. Recompilation is not nice, but also not terribly costly, because computers do it. The real cost is human work induced by non-orthogonality. When a class has a public or protected data member, people are going to use it, and when it changes, things break and have to be fixed.
BTW, “is inherited by a dozen of classes with several layers below the root class” is usually a sign of bad design. Keep inheritance hierarchies flat and concise. Prefer members over base classes: When you decide to use functionality of a class Foo in a class Bar, and there is no compelling reason to let Bar inherit Foo, rather use a member of type Foo.
In C++, the distinction between interfaces and classes is not reified (made into a thing), but still used. It is very useful in many cases to build interfaces, e.g classes consisting of abstract virtual functions, because they avoid many of the troubles of the much-dreaded multiple inheritance.
This is compiler-specific. Don’t worry about it just yet – first understand the language, then it’s implementation.