Thread: creating a list pointer of parent type from base type...

  1. #1
    Registered User
    Join Date
    Sep 2005
    Posts
    40

    Question creating a list pointer of parent type from base type...

    I wasn't sure how to phrase the question in the title. But here is my question. First lets say I have something like this:

    Code:
    class A
    {
    ...
    };
    
    class B 
    {
    ...
    };
    
    class C : public A, public B
    {
    ...
    };
    Where A and B are "interfaces" meaning they contain mostly if not all pure virtual functions.

    What I would like to do is have a main list, in the main part of my code:
    Code:
    std::list<C*> mainList;
    But in the subsystems of the code that only need to know about A and not about B or C, I would like to have a list something like this:

    Code:
    std::list<A*>* alist = &mainlist;
    So in otherwords is there a way to make pointer to a list of type "pointer to A" from a list of type "pointer to C" without having to create a new list and copy the elements one at a time?

    I hope that makes sense.

    Adam.

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Adamkromm View Post
    So in otherwords is there a way to make pointer to a list of type "pointer to A" from a list of type "pointer to C" without having to create a new list and copy the elements one at a time?
    No it is not.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  3. #3
    Registered User gardhr's Avatar
    Join Date
    Apr 2011
    Posts
    151
    Quote Originally Posted by Adamkromm View Post
    So in otherwords is there a way to make pointer to a list of type "pointer to A" from a list of type "pointer to C" without having to create a new list and copy the elements one at a time?
    In practice it should work fine. That said, I'm not so sure that it's guaranteed by the standard, and besides that it's probably considered "bad form". A more conventional approach would be to simply make it a list<A*> to begin with. Manipulating the elements as C*'s would be a simple matter of a cast, after all...
    Last edited by gardhr; 04-14-2012 at 02:47 AM.

  4. #4
    Registered User
    Join Date
    Sep 2005
    Posts
    40
    I guess it's not going to be as easy as I'd hoped.

    gardhr: The only problem with that suggestion is that I have more than one subsystem that needs to know about different parents. Eg, one subsystem needs to know about A, another needs to know about B ...

    Thanks for the quick responses.

  5. #5
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by Adamkromm View Post
    Eg, one subsystem needs to know about A, another needs to know about B ...
    That would be quite easy.
    Have your subsystems use pointers (or references) to A s and B s respectively... but pass around a C*.
    That is all you need to do, according to the Liskov Substitution Principle.. (Unless, I'm myself confused about something here..)

  6. #6
    Registered User
    Join Date
    Sep 2005
    Posts
    40
    Quote Originally Posted by manasij7479 View Post
    That would be quite easy.
    Have your subsystems use pointers (or references) to A s and B s respectively... but pass around a C*.
    That is all you need to do, according to the Liskov Substitution Principle.. (Unless, I'm myself confused about something here..)
    I know that would work -- if I pass around the C*'s individually -- but what I want is to be able to pass around a list of C*'s.

  7. #7
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by Adamkromm View Post
    I know that would work -- if I pass around the C*'s individually -- but what I want is to be able to pass around a list of C*'s.
    Now.. that doesn't make sense!
    If a function is declared as :
    Code:
    void foo(std::list<A*> alist);//or B*
    You can definitely call it with a list<C*> object. That IS the point of having interfaces.

  8. #8
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    You can definitely call it with a list<C*> object.
    You very definitely can't.

    That IS the point of having interfaces.
    The point of interfaces is sharing implementation of logic that uses those interfaces via some form of polymorphisms.

    There is no form of polymorphisms at play in your example.

    Soma

  9. #9
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by phantomotap View Post
    You very definitely can't.
    You're right. I put the example before testing it.
    Apart from being a little embarrassed, I can't understand why it isn't acceptable by the compiler.
    [@Mods:You could split the thread from the point I posted that wrong statement...I'd like some light on it]

  10. #10
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    The compiler essentially writes different forms of the list class depending on the template parameter(s), and they aren't related to one another in a hierarchy. It just so happens that the type contained by the list, which is otherwise separate from the list, is in a hierarchy.

  11. #11
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by whiteflags View Post
    The compiler essentially writes different forms of the list class depending on the template parameter(s), and they aren't related to one another in a hierarchy. It just so happens that the type contained by the list, which is otherwise separate from the list, is in a hierarchy.
    That sure seems to be a deficiency in the design, to me.
    A list of circles, for example, should be able to be count as a list of shapes.

  12. #12
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Your design would mean that any of the lists are related to every other kind of list.

  13. #13
    [](){}(); manasij7479's Avatar
    Join Date
    Feb 2011
    Location
    *nullptr
    Posts
    2,657
    Quote Originally Posted by whiteflags View Post
    Your design would mean that any of the lists are related to every other kind of list.
    No relationship, if the template arguments don't show the relation themselves.

  14. #14
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Well, whiteflags explained the issue well enough, but I'll tackle the next bits.

    It isn't a deficient design; it is only a design that works within the constraints the committee required.

    The containers were designed to need no virtual functions.

    The containers were designed to have minimal and as uniform as possible template parameters.

    The containers would have no way of knowing which classes in the chain to inherit as it is literally impossible to frame this within C++ as any attempt you might make breaks the moment one adds other classes to the hierarchy.

    It is possible to have a container of one type implicitly converted to the same container of a related type by duplicating the converted pointers with all the relevant overloads in place. This doesn't require virtual inheritance, implicit knowledge of the class hierarchy, and allows uniform template parameters. It wasn't done primarily because the techniques weren't well understood and the necessary functionality wasn't widely available at the time the library was being formalized.

    Soma

  15. #15
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    No relationship, if the template arguments don't show the relation themselves.
    This, again, is wrong.

    If `void A::doSomething()' is to call `void C::doSomething()' correctly because of polymorphisms related to inherited types `A' and `C' must be related. This holds true regardless of types `A' and `B'. To prove this to yourself replace `A' with `std::list<A *>', `C' with `std::list<C *>', and `doSomething' with `push_back'.

    [Edit]
    The point here is that for each class in the `A' or `C' hierarchy the container (`std::list<???>') would have to inherit an interface (`std::list<A *>::interface' and `std::list<C *>::interface' for example) for the relationship between the containers to work.
    [/Edit]

    [Edit]
    If your `foo' from post 7 was itself a template the concept works but because of parametric polymorphisms which are very different from those inheritance based.

    Code:
    template<typename T> void foo(std::list<T*> alist);
    Of course, a template of that form has problems of its own.

    Using a typed interface of iterators is certainly a better approach as would be a solution built around the mechanisms I referenced in post 14.
    [/Edit]

    Soma
    Last edited by phantomotap; 04-14-2012 at 02:17 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 03-22-2009, 05:03 AM
  2. Replies: 5
    Last Post: 07-25-2008, 04:37 AM
  3. Replies: 17
    Last Post: 03-06-2008, 02:32 PM
  4. Replies: 4
    Last Post: 08-27-2007, 11:51 PM
  5. finding derived class type of a pointer to a base class
    By LinuxCoder in forum C++ Programming
    Replies: 15
    Last Post: 04-10-2006, 11:08 AM

Tags for this Thread