Thread: Why can't this method take derived class?

  1. #1
    Registered User
    Join Date
    Nov 2006
    Posts
    184

    Why can't this method take derived class?

    Why isn't this working? it says there's no matching function.

    Code:
    //Have these classes (elided methods)
    class Base
    {
    public:
         Base(string name) {...}
    };
    
    class Derived : public Base
    {
    public:
         Derived(String name) : Base( name ) {...}
    };
    void create(std::vector<Base>& arr)
    {
     ...
    }
    
    int main()
    {
         std::vector<Derived> arr;
         create( arr );
    }

  2. #2
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Because polymophism only works when you use pointers or references; and even though the vector is passed by reference, it holds Base objects instead of Base pointers.

  3. #3
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    Don't you think it's about time you get a C++ book?

  4. #4
    Registered User
    Join Date
    Nov 2006
    Posts
    184
    Quote Originally Posted by cpjust View Post
    Because polymophism only works when you use pointers or references; and even though the vector is passed by reference, it holds Base objects instead of Base pointers.
    So how would I make this work? Even when I do this, it doesn't work:

    Code:
    void create(std::vector<Base*>& arr)
    {
     ...
    }
    
    std::vector<Derived*> arr;
    create( arr );

  5. #5
    Ethernal Noob
    Join Date
    Nov 2001
    Posts
    1,901
    with polymorphism if you have a std::vector<Base*>, then you can add a new element as such

    Code:
    arr.push_back(new Derived(...))
    Polymorhism states that a reference to a base object can point to a derived object.

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    No, your vector should hold Base* types in both places. Just like "because I can put an int in a double" doesn't mean that int arr[] and double arr[] are the same.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    Registered User
    Join Date
    Nov 2006
    Posts
    184
    Quote Originally Posted by matsp View Post
    No, your vector should hold Base* types in both places. Just like "because I can put an int in a double" doesn't mean that int arr[] and double arr[] are the same.

    --
    Mats
    Thanks for the reply. I'm just trying to understand this. I thought there was a difference between "an int can be cast to a double" and "a Derived IS also type Base". I don't understand why a vector of Derived pointers can't be cast to/used-as a vector of Base pointers since all Derived objects are also by definition Base objects.

  8. #8
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    You really need to bang your head on a wall until all that Java stuff falls out your ear. Then you'll be making some progress...

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    No, Derived is also of type Base is not true.
    It's true that Derived * is compatible with Base *.

    The difference is between the actual object and the address of the actual object - since the derived one has the same vtable as the base, then it's ok to replace one with the other - as long as you go "down" (towards base) when replacing.

    Also, the derived type's pointer is compatible, but it doesn't mean that a vector containing the base's pointer is compatible with a vector containing the derived pointer - these are two different types and the "explore compatible types" don't even come into it - the template class is not the same instance, so they are not compatible. It's the same as:
    Code:
    struct a
       int x;
       int y;
    };
    struct b
       int x;
       int y;
    };
    
    std::vector<a *> va;
    std::vector<b *> vb;
    va and vb are NOT compatible vectors, becuase the structs have different names - the content in the struct is the same, but the compiler says "You named these structs differently, so you obviously don't mean for them to be the same".

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  10. #10
    Ethernal Noob
    Join Date
    Nov 2001
    Posts
    1,901
    Quote Originally Posted by brewbuck View Post
    You really need to bang your head on a wall until all that Java stuff falls out your ear. Then you'll be making some progress...
    I don't beleive they are so incredibly different that he has to unlearn a language just to pick this one up. I mean, programming is about the concepts, not the language. Just adapt.

  11. #11
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by indigo0086 View Post
    I don't beleive they are so incredibly different that he has to unlearn a language just to pick this one up. I mean, programming is about the concepts, not the language. Just adapt.
    I'm not saying 6tr6tr needs to forget Java, just stop trying to apply that kind of thinking when studying C++.

  12. #12
    Registered User
    Join Date
    Nov 2006
    Posts
    184
    Quote Originally Posted by matsp View Post
    No, Derived is also of type Base is not true.
    It's true that Derived * is compatible with Base *.

    The difference is between the actual object and the address of the actual object - since the derived one has the same vtable as the base, then it's ok to replace one with the other - as long as you go "down" (towards base) when replacing.

    Also, the derived type's pointer is compatible, but it doesn't mean that a vector containing the base's pointer is compatible with a vector containing the derived pointer - these are two different types and the "explore compatible types" don't even come into it - the template class is not the same instance, so they are not compatible. It's the same as:
    Code:
    struct a
       int x;
       int y;
    };
    struct b
       int x;
       int y;
    };
    
    std::vector<a *> va;
    std::vector<b *> vb;
    va and vb are NOT compatible vectors, becuase the structs have different names - the content in the struct is the same, but the compiler says "You named these structs differently, so you obviously don't mean for them to be the same".

    --
    Mats
    THANK YOU! That was a very clear explanation!

    I get it now. It's the fact that vectors, being created from a template, are compiled as completely new classes and the specializations of the template for the vector class do not inherit from other vector class templates/specializations (I don't know if my wording's quite right but I get it now)

    Thanks Mats!

  13. #13
    Registered User
    Join Date
    Nov 2006
    Posts
    184
    Quote Originally Posted by brewbuck View Post
    I'm not saying 6tr6tr needs to forget Java, just stop trying to apply that kind of thinking when studying C++.
    it really is hard because the similarities are there and they sometimes make it harder to "see" things under a diff. light/perspective.

  14. #14
    Ethernal Noob
    Join Date
    Nov 2001
    Posts
    1,901
    just remember, in java everything you create aside from primatives are of <Type>*. They are all pointers and thus polymorphism is automatic.

    But the issue you're having is with templates (java: Generics) not following the same rules as standard polymorphic structures. A vector that holds derived objects is not automatically a subclass of a vector that holds a base object

  15. #15
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    It's all about the Liskov Substitution Principle. Everything you need to know about polymorphism can be directly derived from this simple rule: Type A is a subtype of B if, and only if, an instance of A can be used everywhere an instance of B could be used. (In the context of the C++ language, we're talking about references and pointers to such instances.)

    In particular, consider this:
    Code:
    struct Base { virtual ~Base() {} };
    struct DerivedA : public Base {};
    struct DerivedB : public Base {};
    
    void foo(vector<Base*> &rv)
    {
      rv.push_back(new DerivedB());
    }
    
    int main()
    {
      vector<DerivedA *> v;
      foo(v);
    }
    Consider: v is supposed to hold pointers to DerivedA instances. It is not allowed to insert pointers to DerivedB instances. foo() takes a vector<Base*> and, validly, inserts pointers to DerivedB instances.
    Since vector<Base*> allows insertion of DerivedB instances and vector<DerivedA*> does not, vector<DerivedA*> is not a subtype of vector<Base*>.


    On a side note, it's exactly the same in Java's generics. ArrayList<DerivedA> cannot be passed where an ArrayList<Base> is expected.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Base-class pointer, accessing object from derived class
    By Korhedron in forum C++ Programming
    Replies: 15
    Last Post: 09-28-2008, 05:30 AM
  2. Callback function as class method
    By schifers in forum Windows Programming
    Replies: 39
    Last Post: 05-19-2008, 03:02 PM
  3. C++ Newbie - Derived Class Issue
    By Gipionocheiyort in forum C++ Programming
    Replies: 8
    Last Post: 08-01-2007, 12:20 AM
  4. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  5. Warnings, warnings, warnings?
    By spentdome in forum C Programming
    Replies: 25
    Last Post: 05-27-2002, 06:49 PM