Private Inheritance

Pages: 12
closed account (z05DSL3A)
webJose wrote:
So this IS in fact, a matter of opinion. You believe a stack is not a list. I think a stack is a form of list. So does the OP. So does Microsoft's .Net framework. We all believe stacks and queues are forms of lists. Only thing is that .net call them ICollection and the OP calls them List.

The .net framework does not treat them as a list. As you say it implements the ICollection interface but this has nothing to do with lists. It defines size, enumerators, and synchronization methods for all nongeneric collections. There is a specialization of ICollection, IList, the extends the interface for a list but as a stack does not implement this it is NOT a stack.

My view, a stack IS NOT a list and should not be inherited from one.
Hi Grey Wolf: You are assuming that the OP's List class should be compared directly against List or IList. Do you know if the OP's intention is that exactly? I don't, so I say he's going more basic, like ICollection. Truly there's no direct comparison, so let's not get carried away by comparing names here.

In my view, stacks contain items, can have a count, and most certainly can be enumerated in at least one framework. To me, that is caracteristic of a list (or, better yet, collection).

EDIT: Oh, and I don't have an absolute definition for what a list should be, and probably the OP doesn't either. The OP is defining a List class that may very well contradict your definition of List, or even mine.
Last edited on
PanGalactic wrote:
Newbies almost always overuse inheritance. This is a classic example of when it should not be used. It fails the Liskov substitution test. The stack cannot be used in place of a list.


This.
Lists can be considered stacks, although not conceptually. You can use list anywhere where stack is necessary. So list IS-A stack, but not vice versa. IS-A is not generally reflexive. Stacks can be implemented as adaptor to lists, vectors, even ropes, ...

Private inheritance is not is-a relationship. It is clearly a has-a relationship. If stacks were lists (which as I said, I believe to be the other way around), then public inheritance should've been used.

I believe private inheritance *can* be useful substitute for composition in certain cases:
1. overriding virtual functions to modify the behavior of the base (template method pattern)
2. protected members (composition has no analogy to restrict the access, but it is different)
3. using *dedicated* base class and downcasting to the derived class inside it (when trying to avoid polymorphism overhead and to rename a method with a helper class)

None of those apply here and I currently seem to see no reason for using private inheritance instead of composition. Nothing general-purpose and obvious anyways.

Regards
Guys, you are all being carried away by the name "list". Be more open. You don't know what the OP considers to be a list. For all I know, it seems more like a collection at this point. But if you all insist in talking about lists, let's then define collection, list, stack and then let's see what we should call the OP's List class. Sounds good?

EDIT: Oh, and I don't have an absolute definition for what a list should be, and probably the OP doesn't either. The OP is defining a List class that may very well contradict your definition of List, or even mine.


This isn't a question of preference. An object is defined by behaviour, and the ADT concepts "list" and "stack" are well defined - the only common behaviour between stacks and list is that both can be used to store data. However, conceptionally the two are very distinct things, with a stack supporting only pushing elements on the stop as well as viewing and removing the current top element, whereas a list has no access restrictions on its nodes, meaning you can insert, remove and view elements at any position in the list.

As simeonz pointed out - you can use a list when a stack is expected, but you can't use a stack when a list is expected. In this case, you are just implementing composition with inheritance, which is nothing but a hack without any gains except for a loss of transparency on the implementation level.

In case you didn't understand what I was getting at: Stacks and Lists aren't just mere words you can use however you want. Well, they kinda are, but they are also names for ADT concepts, which are defined by their behaviour.
Last edited on
closed account (z05DSL3A)
webJose wrote:
Hi Grey Wolf: You are assuming that the OP's List class should be compared directly against List or IList....
I was not assuming anything about what the OPs list class was, I was commenting on your argument.
Last edited on
@Grey Wolf: Really? You lost me then, hehe. I have done a lot of commenting.

@hanst99: I understand what you say, and believe me that if I had the same belief that stacks are not lists (and I note here that I have used "list" loosely and the better term is probably "collection"), I would have probably ruled for using a list (again, loose terminology here) as a member variable to store the data.

I still defend what the OP did because I think he/she is trying to do is define a the most basic of lists, which is really just the notion of a collection. Whether or not the design is correct or even complete, that's besides the point right now.

I say: Assuming that an acceptable design is reached, and regardless of the actual word that is being used (list or collection or other), private inheritance is perfectly valid in C++ and there is nothing wrong about it if the developer so chooses to use it. Simeonz agree to it, although he doesn't see his criteria to use it in this particular example. He could be right, but let's remember that what we saw in the original post is far from finished. Simeonz's criteria could eventually be met, who knows! My point is: This is valid C++, and if the user's list is defining a basic concept (like collection), then this is probably OK and probably clear for many developers.

I hope this is getting clear now, hehe. Remember that I am not a natural English speaker, so I might miss the mark here and there from time to time. If you don't understand what I'm saying, this might be the reason. :-P
Last edited on
Indeed there are cases when you need... how should we call it... quasi-stack, whose elements you also can iterate/enumerate, or that you need to access below the top. Say, a debugger does that with the run-time stack, although it is not a stack per-se.

However, private inheritance can only implement HAS-A relationship, because you can neither access the methods from the base, nor upcast from the derived class to the base class. You can not have IS-A with private inheritance.

If you want to have quasi-stack is-a list, you can not rename methods. You can only create new aliases for the old methods, that simply redirect the call. But to ban the old methods entirely from the interface (as with private inheritance) means something else. This is composition. You can always have adaptor instead (with templates or polymorphism), and this is probably the best approach.

The trivia aside, mixing ADT into a chimeric type is IMO permissible, if you know what you are doing.
Last edited on
True simeonz, this is not polymorphism and the OP never said he wanted it. I just point the fact that this is valid and may be the good approach depending on how this develops. This is what I am trying to say. Seems that you do understand my point.
To the OP:

I am working on the same problem right now...

My datastructure library had stack implemented using a linked list (composition), but I found many times I needed to access it like a list, which involved creating a list and adding each element by popping from the stack... I had it set up with an iterator (all of my datastructs have iterators), but some of my functions call for a list, so polymorphism was the only way to pass a stack into it without doing the conversion.

I changed it to inherit from singlelinkedlist publicly, and moved all the publicly inherited methods into the private section of the Stack class, unless I wanted to them exposed (like isEmpty, contains, getSize... ect)...

for instance:
class SingleLinkedList
{
public:
void blocked();
void notBlocked();
};

class Stack : public SingleLinkedList
{
private:
void blocked(){ // call parents, otherwise will not function as a list when using polymorph }
public:
void notBlocked(){ //overloaded or call parents...}
}

void test(SingleLinkedList* list)
{
list->blocked();
}

//compiles
int main()
{
Stack* stack = new Stack();
test(stack);
}

//throws error, obviously :P
int main()
{
Stack* stack = new Stack();
test(stack);
stack->blocked() //error here :PP
}

Regardless of the debate on "Stack is a List", this implementation for me has the best of both worlds, when the user is using it as a stack within a funciton, they can only use the specific public functions... on the other hand when I am writing functions in the library which call for the generality of a list, then I can use a stack or pass in a stack and all is well... it works for me :P

...I am not sure if this is compiler specific, so if it does matter I am using VS2010
Last edited on
Topic archived. No new replies allowed.
Pages: 12