Quote:
Originally Posted by
nuzzle
It's just a play with words. The mess goes away as soon as you stop using inheritance and is-a interchangibly. The stack is-a list in "the inside world" because you say so, not because you use private inheritance.
Never assign responsibilities to C++ it has never assumed. C++ doesn't define modeling relationships, you do. C++ only supplies language constructs to facilitate your modeling.
You have a point, but that is not entirely true. You can't just pick any language construct and map it to an arbitrary relationship, as defined by your modeling paradigm. Why? Because logical relationships require certain conditions to be true, make certain assumptions about the general mechanisms that support the semantics. Language constructs impose some of these constraints or capabilities, so at some level they have an impact on what kind of logical relationships they can represent. But, from there, you can have even more specific interpretations of the relationship, that have nothing to do with the language itself.
My point was, within the scope of the class, you can write
Base *pBase = new PrivatelyDerived();
Within the scope of the class, it's almost as if the keyword private wasn't even used. Within, you can do the same things you can do with public inheritance.
Given all that, I think you can safely say that as far as PrivatelyDerived is concerned, PrivatelyDerived is-a Base (or can be considered as such). Of course, you, as the class' designer, can choose to ignore this fact, and than that relationship will have different semantics, but then you better (1) document that with big flashy letters, and (2) better have a d4mn good reason to use private inheritance.
Because private inheritance, no matter how you interpret it, introduces the same problems as public inheritance, along the lines of the semantic fragile base class problem you spoke of yourself in another thread. (Of course, there is a way to introduce the same set of problems using delegation, but only if you try hard :D.)
For most people, it is hard to see what this class of problems actually is, because they are so subtle an stem from all the convoluted and often not-obvious interaction between a class and a superclass. I mean, if you're unlucky, and if some bad design is involved you can even break the base class just by deriving from it (that would be some sort of "semantic fragile subclass problem"). And when I say break, I don't mean it-wont-compile break; I mean it-compiles-but-it-doesn't-work kind of break.
These problems are all related to the fact that, sooner or later, the code will change. If it's done by someone else, or even by the same developer, but after a relatively long (read: long enough) pause, then if the semantics are not well documented, or even if the documentation isn't studied properly, chances are that the the developer will try to reconstruct the logical model from the code, thus being deceived by the language constructs themselves (but, the language is not to blame).
Good code is its own best documentation. As you're about to add a comment, ask yourself, 'How can I improve the code so that this comment isn't needed?' Improve the code and then document it to make it even clearer. -- Steve McConnell, software engineer and author, from Code Complete
My point is, when you see
class PrivatelyDerived : private Base
it does tell you something. You just can't be sure what is it exactly that it tries to say, at leas not just based on that.