Why it's a pointer not just a class

Discussion in 'C++' started by Michael, Aug 24, 2006.

  1. Michael

    Michael Guest

    Hi,

    typedef std::vector<Vehicle*> VehicleList;

    Vehicle is a UDT, or a class. Why is Vehicle* not just Vehicle in < >.
    Which one is better and why? If you could explain it by laying out some
    codes, it would be highly appreciated!

    Thanks in advance,
    Michael
     
    Michael, Aug 24, 2006
    #1
    1. Advertising

  2. Michael

    Daniel T. Guest

    "Michael" <> wrote:

    > Hi,
    >
    > typedef std::vector<Vehicle*> VehicleList;
    >
    > Vehicle is a UDT, or a class. Why is Vehicle* not just Vehicle in < >.
    > Which one is better and why? If you could explain it by laying out some
    > codes, it would be highly appreciated!


    class Vehicle { };
    class Car : public Vehicle { };

    vector<Vehicle> objVec;
    objVec.push_back( Car() );
    // bad, slices all Car behavior off of the object

    vector<Vehicle*> ptrVec;
    ptrVec.push_back( new Car() ); // good, all Car behavior is maintained

    The problem with the second construct is that the vector doesn't know
    when to delete the objects it contains. Some other object must track
    that. This is often done with some sort of smart pointer.

    vector< shared_ptr< Vehicle > > smartVec;
     
    Daniel T., Aug 24, 2006
    #2
    1. Advertising

  3. Michael

    Salt_Peter Guest

    Michael wrote:
    > Hi,
    >
    > typedef std::vector<Vehicle*> VehicleList;
    >
    > Vehicle is a UDT, or a class. Why is Vehicle* not just Vehicle in < >.
    > Which one is better and why? If you could explain it by laying out some
    > codes, it would be highly appreciated!
    >
    > Thanks in advance,
    > Michael


    Because a Vehicle is abstract. Your goal here is to create a container
    that holds derivatives of the Vehicle class. A Car is a type of
    vehicle. A Truck is a type of Vehicle. A Bus is a type of Vehicle. Why
    have to create a new container for each new type when a container of
    Vehicles can store any type that is related to Vehicles, including a
    mix of Vehicles?

    Polymorphicly, you are creating a container of pointers to Vehicle
    derivatives. That pointer to each element then allows the appropriate
    behaviour to happen: brake(), reverse(), accelerate(). For example, a
    car will not reverse() like a truck - a truck needs to sound a warning
    buzzer first. The pointer essentially lets the vtable do its "magic".

    As far as code is concerned:

    #include <iostream>
    #include <ostream>
    #include <vector>

    class Vehicle
    {
    public:
    Vehicle() { }
    virtual ~Vehicle() { } // virtual
    virtual void reverse() = 0; // pure virtual -- see below
    };

    class Car : public Vehicle
    {
    public:
    Car() { }
    ~Car() { std::cout << "~Car()" << std::endl; }
    void reverse() { std::cout << "reversing" << std::endl; }
    };

    class Truck : public Vehicle
    {
    public:
    Truck() { }
    ~Truck() { std::cout << "~Truck()" << std::endl; }
    void reverse() { std::cout << "buzzer, reversing" << std::endl; }
    };

    int main()
    {
    std::vector< Vehicle* > vehicles;
    // vehicles.push_back( new Vehicle ); error - Vehicle is abstract
    vehicles.push_back( new Car );
    vehicles.push_back( new Truck );

    vehicles[ 0 ]->reverse();
    vehicles[ 1 ]->reverse();

    for ( int i = 0; i < vehicles.size(); ++i ) // or size_t
    {
    delete vehicles[ i ];
    }
    return 0;
    }

    /*
    reversing
    buzzer, reversing
    ~Car()
    ~Truck()
    */

    The destructors are virtual too, they have to be for this to work. The
    reason that reverse() was declared pure virtual in Vehicle is to force
    the client programmer to provide a reverse() member function in order
    to use this system.
    Note that i can write a SportsCar class which derives from Car and
    still use it in the vehicles container. A SportsCar is_a Car which is_a
    Vehicle, hence a SportsCar is_a Vehicle.
    If you don't yet see the benefits of such a system, consider
    encapsulating the std::vector in a container class: all of a sudden,
    you'ld have a container that can hold any Vehicle - including those
    derivatives that have not been created yet (ie: SuperSportsCar or
    TenTonTruck). Without having to modify the container in any way.
    Thats a very powerful concept - your code becomes extensible without
    having to modify the original classes.
     
    Salt_Peter, Aug 24, 2006
    #3
  4. Michael

    Heinz Ozwirk Guest

    "Michael" <> schrieb im Newsbeitrag
    news:...
    > Hi,
    >
    > typedef std::vector<Vehicle*> VehicleList;
    >
    > Vehicle is a UDT, or a class. Why is Vehicle* not just Vehicle in < >.


    Look how Vehicle is defined and how it is used.

    > Which one is better and why?


    Which one is better - a hammer or a tooth brush - and why?

    None is better than the other. It depends on what you want to do.

    Heinz
     
    Heinz Ozwirk, Aug 24, 2006
    #4
  5. On 23 Aug 2006 19:24:13 -0700, "Michael" <> wrote:
    >typedef std::vector<Vehicle*> VehicleList;
    >
    >Vehicle is a UDT, or a class. Why is Vehicle* not just Vehicle in < >.
    >Which one is better and why? If you could explain it by laying out some
    >codes, it would be highly appreciated!


    Good question. The answer simply is that the creator of STL hates OO
    programming. He designed STL for values (ints, doubles, small structs,
    ....) only. BTW, if you want it you can have it, a STL-container for
    (non-copyable) polymorphic objects:
    http://www.codeproject.com/vcpp/stl/ptr_vecto.asp

    Best wishes,
    Roland Pibinger
     
    Roland Pibinger, Aug 24, 2006
    #5
  6. Michael

    Howard Guest

    "Roland Pibinger" <> wrote in message
    news:...
    > On 23 Aug 2006 19:24:13 -0700, "Michael" <> wrote:
    >>typedef std::vector<Vehicle*> VehicleList;
    >>
    >>Vehicle is a UDT, or a class. Why is Vehicle* not just Vehicle in < >.
    >>Which one is better and why? If you could explain it by laying out some
    >>codes, it would be highly appreciated!

    >
    > Good question. The answer simply is that the creator of STL hates OO
    > programming. He designed STL for values (ints, doubles, small structs,
    > ...) only. BTW, if you want it you can have it, a STL-container for
    > (non-copyable) polymorphic objects:
    > http://www.codeproject.com/vcpp/stl/ptr_vecto.asp
    >


    What does the "creator of STL" have to do with anything?

    It's simply a question on the usage of it, and when/why one would prefer to
    use pointers instead of objects in a vector.

    And the answer, as has been pointed out elsethread, is that using pointers
    allows one to take advantage of polymorphism, by storing pointers to base
    class objects while actually instanciating a variety of derived-class
    instances.

    -Howard
     
    Howard, Aug 24, 2006
    #6
  7. Michael

    red floyd Guest

    Howard wrote:
    > "Roland Pibinger" <> wrote in message
    > news:...
    >> On 23 Aug 2006 19:24:13 -0700, "Michael" <> wrote:
    >>> typedef std::vector<Vehicle*> VehicleList;
    >>>
    >>> Vehicle is a UDT, or a class. Why is Vehicle* not just Vehicle in < >.
    >>> Which one is better and why? If you could explain it by laying out some
    >>> codes, it would be highly appreciated!

    >> Good question. The answer simply is that the creator of STL hates OO
    >> programming. He designed STL for values (ints, doubles, small structs,
    >> ...) only. BTW, if you want it you can have it, a STL-container for
    >> (non-copyable) polymorphic objects:
    >> http://www.codeproject.com/vcpp/stl/ptr_vecto.asp
    >>

    >
    > What does the "creator of STL" have to do with anything?
    >
    > It's simply a question on the usage of it, and when/why one would prefer to
    > use pointers instead of objects in a vector.
    >
    > And the answer, as has been pointed out elsethread, is that using pointers
    > allows one to take advantage of polymorphism, by storing pointers to base
    > class objects while actually instanciating a variety of derived-class
    > instances.
    >


    Roland has made his distaste for pointers in Standard containers very
    evident in his other posts.
     
    red floyd, Aug 24, 2006
    #7
  8. On Thu, 24 Aug 2006 15:36:52 GMT, "Howard" <>
    wrote:
    >It's simply a question on the usage of it, and when/why one would prefer to
    >use pointers instead of objects in a vector.
    >And the answer, as has been pointed out elsethread, is that using pointers
    >allows one to take advantage of polymorphism, by storing pointers to base
    >class objects while actually instanciating a variety of derived-class
    >instances.


    Please take a look at other container libraries apart from STL (Rogue
    Wave, MFC, Qt3 ...). They have containers for pointers and containers
    for values. It's just STL that's 'value only'. Rouge Wave e.g. has a
    RWTPtrDlist for pointers and a RWTValDlist vor values. The OP's
    questions is valid.

    Best regards,
    Roland Pibinger
     
    Roland Pibinger, Aug 24, 2006
    #8
  9. On Thu, 24 Aug 2006 16:25:21 GMT, red floyd <> wrote:
    >
    >Roland has made his distaste for pointers in Standard containers very
    >evident in his other posts.


    Of course, that's not a matter of taste or distaste. If you want to
    understand STL you simply need to understand the consequences of value
    semantics.

    Best wishes,
    Roland Pibinger
     
    Roland Pibinger, Aug 24, 2006
    #9
  10. Michael

    Howard Guest

    "Roland Pibinger" <> wrote in message
    news:...
    > On Thu, 24 Aug 2006 15:36:52 GMT, "Howard" <>
    > wrote:
    >>It's simply a question on the usage of it, and when/why one would prefer
    >>to
    >>use pointers instead of objects in a vector.
    >>And the answer, as has been pointed out elsethread, is that using pointers
    >>allows one to take advantage of polymorphism, by storing pointers to base
    >>class objects while actually instanciating a variety of derived-class
    >>instances.

    >
    > Please take a look at other container libraries apart from STL (Rogue
    > Wave, MFC, Qt3 ...). They have containers for pointers and containers
    > for values. It's just STL that's 'value only'. Rouge Wave e.g. has a
    > RWTPtrDlist for pointers and a RWTValDlist vor values. The OP's
    > questions is valid.
    >


    I haven't said that the OP's questions are not valid. I'm suggesting that
    you're not addressing his questions, because you're misunderstanding what
    was asked.

    He asked why some particular code which used a vector was written the way it
    was. Also, he asked when and why one would want to use pointers in a
    vector, as in the example. And that was answered, by me and by others.

    Your response implied he was asking something about why vector the vector
    class itself is written the way it is.

    I could be wrong on what he or you meant, but that's how I (and apparently
    the others) interpreted his questions (and your response).

    -Howard
     
    Howard, Aug 24, 2006
    #10
  11. On Thu, 24 Aug 2006 20:55:46 GMT, "Howard" <>
    wrote:
    >I haven't said that the OP's questions are not valid. I'm suggesting that
    >you're not addressing his questions, because you're misunderstanding what
    >was asked.
    >He asked why some particular code which used a vector was written the way it
    >was. Also, he asked when and why one would want to use pointers in a
    >vector, as in the example. And that was answered, by me and by others.
    >Your response implied he was asking something about why vector the vector
    >class itself is written the way it is.
    >I could be wrong on what he or you meant, but that's how I (and apparently
    >the others) interpreted his questions (and your response).


    Maybe I've iterpreted too much into the question. IMO, it's worth to
    point out that there exist C++ libraries other than STL where a
    container of pointes to Vehicles would be written as e.g.:

    int main(){
    RWTPtrDlist<Vehicle> vehicles;
    //...
    }
    see:
    http://www.roguewave.com/support/docs/sourcepro/edition9/html/toolsref/rwtptrdlist.html


    Best regards,
    Roland Pibinger
     
    Roland Pibinger, Aug 24, 2006
    #11
  12. Michael

    Kai-Uwe Bux Guest

    Roland Pibinger wrote:

    > On Thu, 24 Aug 2006 16:25:21 GMT, red floyd <> wrote:
    >>
    >>Roland has made his distaste for pointers in Standard containers very
    >>evident in his other posts.

    >
    > Of course, that's not a matter of taste or distaste. If you want to
    > understand STL you simply need to understand the consequences of value
    > semantics.


    Well, that goes for the language as a whole. Class type variables in C++
    have value semantics with all its (surprising) consequences like slicing.
    The design decision for the containers in STL is firmly rooted in the
    fundamental feature of C++ to have value semantics and fake/model reference
    semantics through pointers. I do not think that this trait of C++ needs to
    be understood for STL containers separately.


    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Aug 24, 2006
    #12
  13. Roland Pibinger wrote:

    > Maybe I've iterpreted too much into the question. IMO, it's worth to
    > point out that there exist C++ libraries other than STL where a
    > container of pointes to Vehicles would be written as e.g.:
    >
    > int main(){
    > RWTPtrDlist<Vehicle> vehicles;
    > //...
    > }


    There are also libraries with threads, windows, directories, symbolic
    algebra... I don't see the need to point the things the standard library
    does not have. It's shorter the other way.

    --
    Salu2
     
    =?ISO-8859-15?Q?Juli=E1n?= Albo, Aug 25, 2006
    #13
  14. red floyd wrote:
    > Howard wrote:
    >
    >> "Roland Pibinger" <> wrote in message
    >> news:...
    >>
    >>> On 23 Aug 2006 19:24:13 -0700, "Michael" <> wrote:
    >>>
    >>>> typedef std::vector<Vehicle*> VehicleList;
    >>>>
    >>>> Vehicle is a UDT, or a class. Why is Vehicle* not just Vehicle in < >.
    >>>> Which one is better and why? If you could explain it by laying out some
    >>>> codes, it would be highly appreciated!


    <snip>

    >> It's simply a question on the usage of it, and when/why one would
    >> prefer to use pointers instead of objects in a vector.
    >>
    >> And the answer, as has been pointed out elsethread, is that using
    >> pointers allows one to take advantage of polymorphism, by storing
    >> pointers to base class objects while actually instanciating a variety
    >> of derived-class instances.


    I believe another important things is that storing pointers would not
    result in default constructors being called or required. Also, using a
    pointer would not call a copy constructor when placing the object into
    the container.

    --
    Angelo Fraietta
    http://www.smartcontroller.com.au/~angelo/
     
    Angelo Fraietta, Aug 28, 2006
    #14
  15. Michael

    Bo Persson Guest

    "Angelo Fraietta" <> skrev i meddelandet
    news:...
    >
    >
    > red floyd wrote:
    >> Howard wrote:
    >>
    >>> "Roland Pibinger" <> wrote in message
    >>> news:...
    >>>
    >>>> On 23 Aug 2006 19:24:13 -0700, "Michael" <>
    >>>> wrote:
    >>>>
    >>>>> typedef std::vector<Vehicle*> VehicleList;
    >>>>>
    >>>>> Vehicle is a UDT, or a class. Why is Vehicle* not just Vehicle
    >>>>> in < >.
    >>>>> Which one is better and why? If you could explain it by laying
    >>>>> out some
    >>>>> codes, it would be highly appreciated!

    >
    > <snip>
    >
    >>> It's simply a question on the usage of it, and when/why one would
    >>> prefer to use pointers instead of objects in a vector.
    >>>
    >>> And the answer, as has been pointed out elsethread, is that using
    >>> pointers allows one to take advantage of polymorphism, by storing
    >>> pointers to base class objects while actually instanciating a
    >>> variety of derived-class instances.

    >
    > I believe another important things is that storing pointers would
    > not result in default constructors being called or required.


    Default constructors are only required if you actually use them, like
    in resize().

    > Also, using a pointer would not call a copy constructor when placing
    > the object into the container.


    True. You shouldn't store objects that are expensive to copy in a
    standard container.

    On the other hand, the destructor for the elements is not called when
    an element is removed, or when the vectors is destructed. That might
    add additional code and book keeping elsewhere in the program.


    Bo Persson
     
    Bo Persson, Aug 28, 2006
    #15
  16. On Tue, 29 Aug 2006 00:58:37 +0200, "Bo Persson" <> wrote:
    >You shouldn't store objects that are expensive to copy in a
    >standard container.


    It's not mainly a question whether the container elements are
    expensive to copy. The important distinction is between 'values' and
    'objects' (objects in the OO sense). Objects are usually non-copyable
    but may be accessed through multiple references (pointers in C++). STL
    suppports only values. That causes the problems.

    Best wishes,
    Roland Pibinger
     
    Roland Pibinger, Aug 29, 2006
    #16
  17. Michael

    Earl Purple Guest

    Roland Pibinger wrote:
    > Please take a look at other container libraries apart from STL (Rogue
    > Wave, MFC, Qt3 ...). They have containers for pointers and containers
    > for values. It's just STL that's 'value only'. Rouge Wave e.g. has a
    > RWTPtrDlist for pointers and a RWTValDlist vor values. The OP's
    > questions is valid.


    and then there is, of course, boost:

    http://www.boost.org/libs/ptr_container/doc/ptr_container.html

    I'm not sure if this is the same one that was in TheSourceProject or a
    different one. I haven't taken time to look. The boost implementation
    uses "thin templates" i.e. they do the implementation with void*
    pointers and cast both ways. Not sure if that is always safe in a
    mutliple-inheritance situation, but it can have its advantages, i.e.
    far less code generation and even allows you to compile some of it into
    object code to be linked in.
     
    Earl Purple, Aug 29, 2006
    #17
  18. Michael

    I V Guest

    On Tue, 29 Aug 2006 03:30:08 -0700, Earl Purple wrote:
    > and then there is, of course, boost:

    [snip]

    Not to mention boost::indirect_iterator,
    http://boost.org/libs/iterator/doc/indirect_iterator.html

    I'm not familiar with the Rogue Wave library, but a quick glance at the
    documentation suggests that combining the standard containers with
    boost::indirect_iterator accomplishes most, if not all, of what the RW
    pointer containers do (from what I can tell, the RW classes don't deal
    with ownership issues, which is probably the hardest part of a pointer
    container to figure out).
     
    I V, Aug 30, 2006
    #18
  19. On Tue, 29 Aug 2006 22:07:04 -0700, I V <> wrote:
    >On Tue, 29 Aug 2006 03:30:08 -0700, Earl Purple wrote:
    >Not to mention boost::indirect_iterator,
    >http://boost.org/libs/iterator/doc/indirect_iterator.html
    >
    >I'm not familiar with the Rogue Wave library, but a quick glance at the
    >documentation suggests that combining the standard containers with
    >boost::indirect_iterator accomplishes most, if not all, of what the RW
    >pointer containers do


    Nope. When you use eg. std::sort with an boost::indirect_iterator it
    swaps pointed-to objects not pointers. Containers, iterators and
    algorithms need to become pointer aware for a real solution. Moreover,
    the STL templates are notorious for their compiler error messages. An
    iterator adapter adds another level of obfuscation to the program.

    >(from what I can tell, the RW classes don't deal
    >with ownership issues, which is probably the hardest part of a pointer
    >container to figure out).


    Why should a container for pointers be usable only for objects
    allocated with new? Why is such a container supposed to delete
    contained objects? A basic library container should not intermingle
    container functionality and ownership. It should be usable for all
    pointers (to heap-allocatd, to stack and to global objects). IMO, it's
    a design flaw to write containers that insert pointers and require
    that these pointers _must_ point to heap-allocated objects (which are
    later deleted by the container). Of course, one can implement
    ownership semantics on top of a basic pointer container but to build
    ownership (and transfer of ownership to the container) into the
    container is (put mildly) a highly questionable design decision.

    Best wishes,
    Roland Pibinger
     
    Roland Pibinger, Aug 30, 2006
    #19
  20. Michael

    Earl Purple Guest

    Roland Pibinger wrote:
    > Why should a container for pointers be usable only for objects
    > allocated with new? Why is such a container supposed to delete
    > contained objects?


    It shouldn't have to. But there are containers for those that don't.
    When I saw boost's ptr_vector my first impression was that perhaps
    there should have been a custom deleter option, although the
    custom-deleter would need to be the same for every object in the
    vector.

    If you want custom deleters for each pointer then use vector<
    shared_ptr >.
    And for sort you have the option of passing ni your own predicate that
    can do *iter1 < *iter2

    > A basic library container should not intermingle
    > container functionality and ownership. It should be usable for all
    > pointers (to heap-allocatd, to stack and to global objects). IMO, it's
    > a design flaw to write containers that insert pointers and require
    > that these pointers _must_ point to heap-allocated objects (which are
    > later deleted by the container).


    It's not a design flaw it's a design decision. You use that collection
    when you want that functionality. When you don't, you use a different
    one. It enables you to use std::generate to fill the collection where
    std::generate calls new.

    > Of course, one can implement
    > ownership semantics on top of a basic pointer container but to build
    > ownership (and transfer of ownership to the container) into the
    > container is (put mildly) a highly questionable design decision.


    In the absence of real garbage collection, you must provide ownership
    semantics. And assuming you don't want to use shared_ptr, using a
    collection to handle the it for you is not unreasonable.

    I do think though that there should be an option of a custom deleter,
    albeit one deleter for every item in the collection so there is no
    option to mix and match. Not unless the deleter is smart enough to do
    that, that is.
     
    Earl Purple, Aug 30, 2006
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Tom Dyess
    Replies:
    2
    Views:
    478
    =?UTF-8?b?TMSByrtpZSBUZWNoaWU=?=
    Jan 20, 2005
  2. tirath
    Replies:
    3
    Views:
    711
    Ivan Vecerina
    Oct 12, 2003
  3. JKop
    Replies:
    5
    Views:
    371
    Jerry Coffin
    Sep 7, 2004
  4. Mr. SweatyFinger

    why why why why why

    Mr. SweatyFinger, Nov 28, 2006, in forum: ASP .Net
    Replies:
    4
    Views:
    911
    Mark Rae
    Dec 21, 2006
  5. Mr. SweatyFinger
    Replies:
    2
    Views:
    2,002
    Smokey Grindel
    Dec 2, 2006
Loading...

Share This Page