Inheriting a vector

Discussion in 'C++' started by toton, Sep 26, 2006.

  1. toton

    toton Guest

    Hi,
    I want to have a vector like class with some additional functionality
    (cosmetic one). So can I inherit a vector class to add the addition
    function like,

    CorresVector : public vector<Corres>{
    public:
    void addCorres(Corres& c); //it do little more than push_back
    function.
    }
    Or I need to do a composition to do it (i.e storing the vector inside
    Corresvector & delegating the necessary functionality). I want to know
    that whether in this case (inheriting) is allowed for containers, i.e
    will the container will get freed when CorresVector gets destoryed (i.e
    vector has a virtual destructor which gets called?)

    abir
     
    toton, Sep 26, 2006
    #1
    1. Advertising

  2. toton

    Noah Roberts Guest

    toton wrote:
    > Hi,
    > I want to have a vector like class with some additional functionality
    > (cosmetic one). So can I inherit a vector class to add the addition
    > function like,
    >
    > CorresVector : public vector<Corres>{
    > public:
    > void addCorres(Corres& c); //it do little more than push_back
    > function.
    > }
    > Or I need to do a composition to do it (i.e storing the vector inside
    > Corresvector & delegating the necessary functionality). I want to know
    > that whether in this case (inheriting) is allowed for containers, i.e
    > will the container will get freed when CorresVector gets destoryed (i.e
    > vector has a virtual destructor which gets called?)


    No, vector does not have a virtual destructor. It doesn't have any
    virtual functions. You can inherit from a vector but you can't do so
    polymorphically.
     
    Noah Roberts, Sep 26, 2006
    #2
    1. Advertising

  3. toton

    Frank Guest

    toton wrote:

    > Hi,
    > I want to have a vector like class with some additional functionality
    > (cosmetic one). So can I inherit a vector class to add the addition
    > function like,
    >
    > CorresVector : public vector<Corres>{
    > public:
    > void addCorres(Corres& c); //it do little more than push_back
    > function.
    > }
    > Or I need to do a composition to do it (i.e storing the vector inside
    > Corresvector & delegating the necessary functionality). I want to know
    > that whether in this case (inheriting) is allowed for containers, i.e
    > will the container will get freed when CorresVector gets destoryed (i.e
    > vector has a virtual destructor which gets called?)
    >
    > abir


    Hi abir,

    std::vector does not have a virtual destructor.
    But it would only need one, if you delete a CorresVector through a pointer
    to a base class.

    As for the question whether it is the "right" approach, use google and you
    will find a lot of different opinions (see e.g.
    http://www.thescripts.com/forum/thread63869.html).

    Cheers,
    Frank
     
    Frank, Sep 26, 2006
    #3
  4. toton

    toton Guest

    Frank wrote:
    > toton wrote:
    >
    > > Hi,
    > > I want to have a vector like class with some additional functionality
    > > (cosmetic one). So can I inherit a vector class to add the addition
    > > function like,
    > >
    > > CorresVector : public vector<Corres>{
    > > public:
    > > void addCorres(Corres& c); //it do little more than push_back
    > > function.
    > > }
    > > Or I need to do a composition to do it (i.e storing the vector inside
    > > Corresvector & delegating the necessary functionality). I want to know
    > > that whether in this case (inheriting) is allowed for containers, i.e
    > > will the container will get freed when CorresVector gets destoryed (i.e
    > > vector has a virtual destructor which gets called?)
    > >
    > > abir

    >
    > Hi abir,
    >
    > std::vector does not have a virtual destructor.
    > But it would only need one, if you delete a CorresVector through a pointer
    > to a base class.
    >
    > As for the question whether it is the "right" approach, use google and you
    > will find a lot of different opinions (see e.g.
    > http://www.thescripts.com/forum/thread63869.html).

    I have a Session class which stores the CorresVector, not a pointer or
    reference. and Session class destructor will thus automatically call
    CorresVector. Hence there is no ploymorphic behavior. I hope there will
    not be any memory leak therefore.
    Otherwise it is pain to delegate a lot of method including container
    traits & iterators.
    Religion is definitely a question, may think later of delegating (or
    protected inheritence) if my class sufficiently differs from vector or
    any other misuse question comes (I know Java Stack is inherited from
    Vector ! ).
    > Cheers,
    > Frank
     
    toton, Sep 26, 2006
    #4
  5. toton

    toton Guest

    Frank wrote:
    > toton wrote:
    >
    > > Hi,
    > > I want to have a vector like class with some additional functionality
    > > (cosmetic one). So can I inherit a vector class to add the addition
    > > function like,
    > >
    > > CorresVector : public vector<Corres>{
    > > public:
    > > void addCorres(Corres& c); //it do little more than push_back
    > > function.
    > > }
    > > Or I need to do a composition to do it (i.e storing the vector inside
    > > Corresvector & delegating the necessary functionality). I want to know
    > > that whether in this case (inheriting) is allowed for containers, i.e
    > > will the container will get freed when CorresVector gets destoryed (i.e
    > > vector has a virtual destructor which gets called?)
    > >
    > > abir

    >
    > Hi abir,
    >
    > std::vector does not have a virtual destructor.
    > But it would only need one, if you delete a CorresVector through a pointer
    > to a base class.
    >
    > As for the question whether it is the "right" approach, use google and you
    > will find a lot of different opinions (see e.g.
    > http://www.thescripts.com/forum/thread63869.html).

    I have a Session class which stores the CorresVector, not a pointer or
    reference. and Session class destructor will thus automatically call
    CorresVector. Hence there is no ploymorphic behavior. I hope there will
    not be any memory leak therefore.
    Otherwise it is pain to delegate a lot of method including container
    traits & iterators.
    Religion is definitely a question, may think later of delegating (or
    protected inheritence) if my class sufficiently differs from vector or
    any other misuse question comes (I know Java Stack is inherited from
    Vector ! ).
    Thanks for quick answer.
    > Cheers,
    > Frank
     
    toton, Sep 26, 2006
    #5
  6. toton

    Salt_Peter Guest

    toton wrote:
    > Hi,
    > I want to have a vector like class with some additional functionality
    > (cosmetic one). So can I inherit a vector class to add the addition
    > function like,
    >
    > CorresVector : public vector<Corres>{
    > public:
    > void addCorres(Corres& c); //it do little more than push_back
    > function.
    > }
    > Or I need to do a composition to do it (i.e storing the vector inside
    > Corresvector & delegating the necessary functionality). I want to know
    > that whether in this case (inheriting) is allowed for containers, i.e
    > will the container will get freed when CorresVector gets destoryed (i.e
    > vector has a virtual destructor which gets called?)
    >
    > abir


    You should not derive from STL container classes. Their destructors are
    not virtual.
    Although, in my book, composition can be a form of private inheritence.
    Why not template the class? In your example, if element class Corres,
    whatever that is, overloads the global op<<, you can add features as
    shown below. Note that both primitive int and class std::string already
    have an overloaded operator<<.

    The point here is that if you are going to compose with a std::vector,
    do it to add features, otherwise you would not need to wrap the
    container.
    How you do that is not very complicated:

    a) learn how to declare and use templates
    b) pass by reference
    c) dependant types need the typename keyword
    d) overload operators

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

    template< typename T >
    class Vector
    {
    std::vector< T > vt;
    public:
    Vector() : vt() { } // an empty vector of TsSince primitive types
    like int and other classes like std::string already have an overload
    for global op<<, i can iterate through the elements simply by writing:

    std::cout << name_of_container;
    ~Vector() { }
    /* member functions */
    size_t size() const { return vt.size(); }
    void push_back( const T& r_t ) { vt.push_back( r_t ); }
    /* friend op */
    friend
    std::eek:stream&
    operator<<( std::eek:stream& os, Vector< T >& r_v )
    { // std::vector<T>::iterator is a dependant type
    typedef typename std::vector< T >::iterator VIter;
    VIter iter = r_v.vt.begin();
    for ( iter; iter != r_v.vt.end(); ++iter )
    {
    os << *iter << std::endl;
    }
    return os;
    }
    };

    int main()
    {
    Vector< int > integers;
    for ( int n = 0; n < 5; ++n )
    {
    integers.push_back( n );
    }
    std::cout << integers; // op<< overload

    Vector< std::string > strings;
    strings.push_back( "first string" );
    strings.push_back( "second string" );
    strings.push_back( "third string" );
    strings.push_back( "fourth string" );
    std::cout << strings; // op<< overload

    return 0;
    }

    /*
    0
    1
    2
    3
    4
    first string
    second string
    third string
    fourth string
    */
     
    Salt_Peter, Sep 26, 2006
    #6
  7. toton

    toton Guest

    Salt_Peter wrote:
    > toton wrote:
    > > Hi,
    > > I want to have a vector like class with some additional functionality
    > > (cosmetic one). So can I inherit a vector class to add the addition
    > > function like,
    > >
    > > CorresVector : public vector<Corres>{
    > > public:
    > > void addCorres(Corres& c); //it do little more than push_back
    > > function.
    > > }
    > > Or I need to do a composition to do it (i.e storing the vector inside
    > > Corresvector & delegating the necessary functionality). I want to know
    > > that whether in this case (inheriting) is allowed for containers, i.e
    > > will the container will get freed when CorresVector gets destoryed (i.e
    > > vector has a virtual destructor which gets called?)
    > >
    > > abir

    >
    > You should not derive from STL container classes. Their destructors are
    > not virtual.
    > Although, in my book, composition can be a form of private inheritence.
    > Why not template the class? In your example, if element class Corres,
    > whatever that is, overloads the global op<<, you can add features as
    > shown below. Note that both primitive int and class std::string already
    > have an overloaded operator<<.
    >
    > The point here is that if you are going to compose with a std::vector,
    > do it to add features, otherwise you would not need to wrap the
    > container.
    > How you do that is not very complicated:
    >
    > a) learn how to declare and use templates
    > b) pass by reference
    > c) dependant types need the typename keyword
    > d) overload operators
    >
    > #include <iostream>
    > #include <ostream>
    > #include <string>
    > #include <vector>
    >
    > template< typename T >
    > class Vector
    > {
    > std::vector< T > vt;
    > public:
    > Vector() : vt() { } // an empty vector of TsSince primitive types
    > like int and other classes like std::string already have an overload
    > for global op<<, i can iterate through the elements simply by writing:
    >
    > std::cout << name_of_container;
    > ~Vector() { }
    > /* member functions */
    > size_t size() const { return vt.size(); }
    > void push_back( const T& r_t ) { vt.push_back( r_t ); }
    > /* friend op */
    > friend
    > std::eek:stream&
    > operator<<( std::eek:stream& os, Vector< T >& r_v )
    > { // std::vector<T>::iterator is a dependant type
    > typedef typename std::vector< T >::iterator VIter;
    > VIter iter = r_v.vt.begin();
    > for ( iter; iter != r_v.vt.end(); ++iter )
    > {
    > os << *iter << std::endl;
    > }
    > return os;
    > }
    > };
    >
    > int main()
    > {
    > Vector< int > integers;
    > for ( int n = 0; n < 5; ++n )
    > {
    > integers.push_back( n );
    > }
    > std::cout << integers; // op<< overload
    >
    > Vector< std::string > strings;
    > strings.push_back( "first string" );
    > strings.push_back( "second string" );
    > strings.push_back( "third string" );
    > strings.push_back( "fourth string" );
    > std::cout << strings; // op<< overload
    >
    > return 0;
    > }
    >
    > /*
    > 0
    > 1
    > 2
    > 3
    > 4
    > first string
    > second string
    > third string
    > fourth string
    > */

    This is the other option which I thought (and mentioned in my first
    post). Using delegate is always better, I think. It both protects
    security, and makes a cleaner interface (I had mentioned like Java
    Vector & Stack). And templating Vector is not usefull for my case, as I
    am going to use only and only CorresVector where some additional
    methods are there, to perform some additional job, and may want to
    build a library from that directly for my core engine part of the
    application. Not that it can not be done otherway, (like performing
    the tasks after push_back operation, say some notification event
    handling) but assigning the tasks in the operation itself secures code.

    However unlike the code you presented, I need many features of vector
    rather than just push_back. Most importantly, I need the iterator
    functionality, and want to apply many stl algorithms to CorresVector
    just like vector. That says I need to delegate many more functions
    rather than size & push_back( say aoo of the iterator traits, const &
    non const vercion of begin end etc, reserve, indexing operators, at and
    others). It is not difficult, it is tedious!
    And in code CorresVector is going to be used only one place, i.e inside
    Session class, like,
    class Session{
    private:
    CorresVector _corres;
    };
    and some reference get methods (const & non const). There is no other
    place where it will be used (there is no other place there it can be
    used also :) ). Thus I think it will not cause any memory leak in this
    particular case(i.e not freeing the elements on destruction). Session
    class has a virtual destructor, and hence it will always get destroyed
    even when inheriting & storing in SessionManager (a singleton) like
    FileSession, OnlineSession etc.
    Can you say a yes/no about risk to this specific case?
    For general case, I like your answer, and sooner or later will
    implement it.
    btw Corres means Correspondence (a special kind of distance structure)

    Thanks for the reply & the worning.
     
    toton, Sep 26, 2006
    #7
  8. toton

    Gavin Deane Guest

    Salt_Peter wrote:
    > toton wrote:
    > > Hi,
    > > I want to have a vector like class with some additional functionality
    > > (cosmetic one). So can I inherit a vector class to add the addition
    > > function like,

    >
    > You should not derive from STL container classes. Their destructors are
    > not virtual.


    That should read "you should not polymorphically delete objects of
    types derived from STL container classes. STL container classes do not
    have virtual destructors."

    > Although, in my book, composition can be a form of private inheritence.
    > Why not template the class? In your example, if element class Corres,
    > whatever that is, overloads the global op<<, you can add features as
    > shown below. Note that both primitive int and class std::string already
    > have an overloaded operator<<.
    >
    > The point here is that if you are going to compose with a std::vector,
    > do it to add features, otherwise you would not need to wrap the
    > container.
    > How you do that is not very complicated:
    >
    > a) learn how to declare and use templates
    > b) pass by reference
    > c) dependant types need the typename keyword
    > d) overload operators
    >
    > #include <iostream>
    > #include <ostream>
    > #include <string>
    > #include <vector>
    >
    > template< typename T >
    > class Vector
    > {
    > std::vector< T > vt;
    > public:
    > Vector() : vt() { } // an empty vector of TsSince primitive types
    > like int and other classes like std::string already have an overload
    > for global op<<, i can iterate through the elements simply by writing:
    >
    > std::cout << name_of_container;
    > ~Vector() { }
    > /* member functions */
    > size_t size() const { return vt.size(); }
    > void push_back( const T& r_t ) { vt.push_back( r_t ); }
    > /* friend op */
    > friend
    > std::eek:stream&
    > operator<<( std::eek:stream& os, Vector< T >& r_v )
    > { // std::vector<T>::iterator is a dependant type
    > typedef typename std::vector< T >::iterator VIter;
    > VIter iter = r_v.vt.begin();
    > for ( iter; iter != r_v.vt.end(); ++iter )
    > {
    > os << *iter << std::endl;
    > }
    > return os;
    > }
    > };


    How is that class superior to this? If used with your program below it
    produces the same output.

    template <typename T>
    class Vector : public std::vector<T>
    {
    friend std::eek:stream& operator<<(std::eek:stream& os, Vector< T >& r_v)
    {
    typedef typename std::vector< T >::iterator VIter;
    VIter iter = r_v.begin();
    for ( iter; iter != r_v.end(); ++iter )
    {
    os << *iter << std::endl;
    }
    return os;
    }
    };

    > int main()
    > {
    > Vector< int > integers;
    > for ( int n = 0; n < 5; ++n )
    > {
    > integers.push_back( n );
    > }
    > std::cout << integers; // op<< overload
    >
    > Vector< std::string > strings;
    > strings.push_back( "first string" );
    > strings.push_back( "second string" );
    > strings.push_back( "third string" );
    > strings.push_back( "fourth string" );
    > std::cout << strings; // op<< overload


    But your class can't do this unless you go back and change it.

    strings.pop_back();
    std::cout << strings;

    >
    > return 0;
    > }
    >
    > /*
    > 0
    > 1
    > 2
    > 3
    > 4
    > first string
    > second string
    > third string
    > fourth string

    first string
    second string
    third string
    > */


    Gavin Deane
     
    Gavin Deane, Sep 26, 2006
    #8
  9. toton

    Pete Becker Guest

    Noah Roberts wrote:
    > toton wrote:
    >> Hi,
    >> I want to have a vector like class with some additional functionality
    >> (cosmetic one). So can I inherit a vector class to add the addition
    >> function like,
    >>
    >> CorresVector : public vector<Corres>{
    >> public:
    >> void addCorres(Corres& c); //it do little more than push_back
    >> function.
    >> }
    >> Or I need to do a composition to do it (i.e storing the vector inside
    >> Corresvector & delegating the necessary functionality). I want to know
    >> that whether in this case (inheriting) is allowed for containers, i.e
    >> will the container will get freed when CorresVector gets destoryed (i.e
    >> vector has a virtual destructor which gets called?)

    >
    > No, vector does not have a virtual destructor. It doesn't have any
    > virtual functions. You can inherit from a vector but you can't do so
    > polymorphically.
    >


    But that's really two different questions. Yes, when CorresVector gets
    destroyed, its base will, too. No, if you have a pointer to the base and
    you delete that, you have no guarantees of what will happen, because the
    base type does not have a virtual destructor.

    --

    -- Pete

    Author of "The Standard C++ Library Extensions: a Tutorial and
    Reference." For more information about this book, see
    www.petebecker.com/tr1book.
     
    Pete Becker, Sep 26, 2006
    #9
  10. toton

    Salt_Peter Guest

    Gavin Deane wrote:
    > Salt_Peter wrote:
    > > toton wrote:
    > > > Hi,
    > > > I want to have a vector like class with some additional functionality
    > > > (cosmetic one). So can I inherit a vector class to add the addition
    > > > function like,

    > >
    > > You should not derive from STL container classes. Their destructors are
    > > not virtual.

    >
    > That should read "you should not polymorphically delete objects of
    > types derived from STL container classes. STL container classes do

    not
    > have virtual destructors."


    yes, of course. But isn't that the goal here?
    Otherwise, why bother inheriting from a std::vector?

    >
    > > Although, in my book, composition can be a form of private inheritence.
    > > Why not template the class? In your example, if element class Corres,
    > > whatever that is, overloads the global op<<, you can add features as
    > > shown below. Note that both primitive int and class std::string already
    > > have an overloaded operator<<.
    > >
    > > The point here is that if you are going to compose with a std::vector,
    > > do it to add features, otherwise you would not need to wrap the
    > > container.
    > > How you do that is not very complicated:
    > >
    > > a) learn how to declare and use templates
    > > b) pass by reference
    > > c) dependant types need the typename keyword
    > > d) overload operators
    > >
    > > #include <iostream>
    > > #include <ostream>
    > > #include <string>
    > > #include <vector>
    > >
    > > template< typename T >
    > > class Vector
    > > {
    > > std::vector< T > vt;
    > > public:
    > > Vector() : vt() { } // an empty vector of TsSince primitive types
    > > like int and other classes like std::string already have an overload
    > > for global op<<, i can iterate through the elements simply by writing:
    > >
    > > std::cout << name_of_container;
    > > ~Vector() { }
    > > /* member functions */
    > > size_t size() const { return vt.size(); }
    > > void push_back( const T& r_t ) { vt.push_back( r_t ); }
    > > /* friend op */
    > > friend
    > > std::eek:stream&
    > > operator<<( std::eek:stream& os, Vector< T >& r_v )
    > > { // std::vector<T>::iterator is a dependant type
    > > typedef typename std::vector< T >::iterator VIter;
    > > VIter iter = r_v.vt.begin();
    > > for ( iter; iter != r_v.vt.end(); ++iter )
    > > {
    > > os << *iter << std::endl;
    > > }
    > > return os;
    > > }
    > > };

    >
    > How is that class superior to this? If used with your program below it
    > produces the same output.


    My class is not superior in any way unless there is a need to protect
    the internals or if polymorphism is involved.

    >
    > template <typename T>
    > class Vector : public std::vector<T>
    > {


    If you inherit publicly, friend is no longer required, the std::vector
    is directly accessible.

    > friend std::eek:stream& operator<<(std::eek:stream& os, Vector< T >& r_v)
    > {
    > typedef typename std::vector< T >::iterator VIter;
    > VIter iter = r_v.begin();
    > for ( iter; iter != r_v.end(); ++iter )
    > {
    > os << *iter << std::endl;
    > }
    > return os;
    > }
    > };


    or

    #include <iostream>
    #include <ostream>
    #include <string>
    #include <vector>
    #include <iterator>

    template< typename T >
    class Vector : public std::vector< T >
    {
    };

    template< typename T >
    std::eek:stream&
    operator<<( std::eek:stream& os, Vector< T >& r_v )
    {
    std::copy( r_v.begin(),
    r_v.end(),
    std::eek:stream_iterator< T > ( std::cout , "\n") );
    }

    Which again brings us right back to the crux of the issue. In such a
    case, why bother inheriting from std::vector? What is the reason?

    >
    > > int main()
    > > {
    > > Vector< int > integers;
    > > for ( int n = 0; n < 5; ++n )
    > > {
    > > integers.push_back( n );
    > > }
    > > std::cout << integers; // op<< overload
    > >
    > > Vector< std::string > strings;
    > > strings.push_back( "first string" );
    > > strings.push_back( "second string" );
    > > strings.push_back( "third string" );
    > > strings.push_back( "fourth string" );
    > > std::cout << strings; // op<< overload

    >
    > But your class can't do this unless you go back and change it.
    >
    > strings.pop_back();
    > std::cout << strings;


    Thats obvious. The rest of the interface was not implemented.

    >
    > Gavin Deane
     
    Salt_Peter, Sep 26, 2006
    #10
  11. toton

    Gavin Deane Guest

    Salt_Peter wrote:
    > Gavin Deane wrote:
    > > Salt_Peter wrote:
    > > > toton wrote:
    > > > > Hi,
    > > > > I want to have a vector like class with some additional functionality
    > > > > (cosmetic one). So can I inherit a vector class to add the addition
    > > > > function like,
    > > >
    > > > You should not derive from STL container classes. Their destructors are
    > > > not virtual.

    > >
    > > That should read "you should not polymorphically delete objects of
    > > types derived from STL container classes. STL container classes do

    > not
    > > have virtual destructors."

    >
    > yes, of course. But isn't that the goal here?
    > Otherwise, why bother inheriting from a std::vector?


    I doubt polymorphism is the OP's goal, since std::vector doesn't have
    any virtual member functions at all.

    > #include <iostream>
    > #include <ostream>
    > #include <string>
    > #include <vector>
    > #include <iterator>
    >
    > template< typename T >
    > class Vector : public std::vector< T >
    > {
    > };
    >
    > template< typename T >
    > std::eek:stream&
    > operator<<( std::eek:stream& os, Vector< T >& r_v )
    > {
    > std::copy( r_v.begin(),
    > r_v.end(),
    > std::eek:stream_iterator< T > ( std::cout , "\n") );
    > }
    >
    > Which again brings us right back to the crux of the issue. In such a
    > case, why bother inheriting from std::vector? What is the reason?


    That's a design decision for the OP. Depending on the design goal,
    there may be options superior to inheritance. Composition may or may
    not be one of them.

    The point I was making was that lack of a virtual destructor is not
    sufficient reason for rejecting inheritance, and that using composition
    instead is not necessarily better because you, the programmer, are
    required to manually forward all those parts of the std::vector
    interface that you need to be accessible to users of the containing
    class, whereas inheritance gives you that forwarding for free.

    > > But your class can't do this unless you go back and change it.


    > > strings.pop_back();
    > > std::cout << strings;


    > Thats obvious. The rest of the interface was not implemented.


    The fact that it has to be implemented manually is the problem.

    Gavin Deane
     
    Gavin Deane, Sep 26, 2006
    #11
  12. toton wrote:
    > Hi,
    > I want to have a vector like class with some additional functionality
    > (cosmetic one). So can I inherit a vector class to add the addition
    > function like,
    >
    > CorresVector : public vector<Corres>{
    > public:
    > void addCorres(Corres& c); //it do little more than push_back
    > function.
    > }


    You are basically wanting to "inherit for convenience" - you seem like
    a sensible fellow who understands that (a) there are issues with this
    approach and (b) knows what those issues are (or at least you do know
    from others' replies), so I say go for it.
     
    tragomaskhalos, Sep 26, 2006
    #12
  13. toton

    Jerry Coffin Guest

    In article <>,
    says...
    > Hi,
    > I want to have a vector like class with some additional functionality
    > (cosmetic one). So can I inherit a vector class to add the addition
    > function like,
    >
    > CorresVector : public vector<Corres>{
    > public:
    > void addCorres(Corres& c); //it do little more than push_back
    > function.
    > }
    > Or I need to do a composition to do it (i.e storing the vector inside
    > Corresvector & delegating the necessary functionality). I want to know
    > that whether in this case (inheriting) is allowed for containers, i.e
    > will the container will get freed when CorresVector gets destoryed (i.e
    > vector has a virtual destructor which gets called?)


    std::vector doesn't have a virtual dtor (or any virtual functions for
    that matter). Since the dtor isn't virtual this would lead to undefined
    behavior, but it's easy to do by accident because public inheritance
    allows implicit conversion to the base class.

    While composition is clearly an option, you might also want to consider
    private inheritance:

    class CorresVector : private std::vector<Corres> {
    public:
    using vector::begin;
    using vector::end;
    using vector::erase;
    void add(Corres const &c) { push_back(c); }
    // ...
    };

    Public inheritance is easy, but somewhat dangerous because you can
    accidentally (implicitly) convert a pointer to your derived class into a
    pointer to the base -- and destroying that leads to undefined behavior.

    Composition gives safety, but writing forwarding functions adds work.
    Private inheritance is more or less a halfway point, providing the
    safety of composition with a little less work -- using declarations are
    clearly simpler than forwarding functions, though obviously more work
    than a public base class.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, Sep 27, 2006
    #13
  14. toton

    Pete Becker Guest

    Jerry Coffin wrote:
    > In article <>,
    > says...
    >> Hi,
    >> I want to have a vector like class with some additional functionality
    >> (cosmetic one). So can I inherit a vector class to add the addition
    >> function like,
    >>
    >> CorresVector : public vector<Corres>{
    >> public:
    >> void addCorres(Corres& c); //it do little more than push_back
    >> function.
    >> }
    >> Or I need to do a composition to do it (i.e storing the vector inside
    >> Corresvector & delegating the necessary functionality). I want to know
    >> that whether in this case (inheriting) is allowed for containers, i.e
    >> will the container will get freed when CorresVector gets destoryed (i.e
    >> vector has a virtual destructor which gets called?)

    >
    > std::vector doesn't have a virtual dtor (or any virtual functions for
    > that matter). Since the dtor isn't virtual this would lead to undefined
    > behavior


    No, there's nothing undefined in destroying an object whose type is
    derived from a type that does not have a virtual destructor. You ONLY
    get undefined behavior if you delete such an object through a pointer to
    its base type.

    , but it's easy to do by accident because public inheritance
    > allows implicit conversion to the base class.
    >


    This has nothing to do with destruction. Converting to the base type is
    slicing, and it's a potential problem regardless of whether the base
    type has virtual functions.

    >
    > Public inheritance is easy, but somewhat dangerous because you can
    > accidentally (implicitly) convert a pointer to your derived class into a
    > pointer to the base -- and destroying that leads to undefined behavior.
    >
    > Composition gives safety, but writing forwarding functions adds work.
    > Private inheritance is more or less a halfway point, providing the
    > safety of composition with a little less work -- using declarations are
    > clearly simpler than forwarding functions, though obviously more work
    > than a public base class.
    >


    Okay.

    --

    -- Pete

    Author of "The Standard C++ Library Extensions: a Tutorial and
    Reference." For more information about this book, see
    www.petebecker.com/tr1book.
     
    Pete Becker, Sep 27, 2006
    #14
  15. toton

    Jerry Coffin Guest

    In article <>,
    says...

    [ ... ]

    > No, there's nothing undefined in destroying an object whose type is
    > derived from a type that does not have a virtual destructor. You ONLY
    > get undefined behavior if you delete such an object through a pointer to
    > its base type.


    Well, even I can't figure out what I wrote when you pull it apart into
    half-sentences, and reply to bits and pieces that were never intended to
    represent a complete thought. To clarify what I was trying to say:

    1) if you have code like this:

    class base {}; // note lack of virtual dtor
    class derived : public base {};

    base *b = new derived;
    // ...
    delete b;

    You'd get undefined behavior. and:

    2) There's absolutely NOTHING you can do in 'derived' to prevent it from
    being used in that fashion (or many similar ones that cause similar
    problems).

    What it comes down to is fairly simple: by using public derivation,
    you've _promised_ that a derived can be substituted for a base under any
    and all possible circumstances. The problem arises for the simple reason
    that this is a lie -- under at least one circumstance (destruction) the
    substitution leads to undefined behavior.

    In short, even though you _can_ get away with this as long as you're
    sufficiently careful about how you use it, it's a lousy idea. Public
    derivation has a specific meaning. Unless you really mean it, you
    shouldn't say it by using public derivation. Public derivation from a
    base class without a virtual dtor asserts a falsehood.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, Sep 28, 2006
    #15
  16. toton

    Kai-Uwe Bux Guest

    Jerry Coffin wrote:

    > In article <>,
    > says...
    >
    > [ ... ]
    >
    >> No, there's nothing undefined in destroying an object whose type is
    >> derived from a type that does not have a virtual destructor. You ONLY
    >> get undefined behavior if you delete such an object through a pointer to
    >> its base type.

    >
    > Well, even I can't figure out what I wrote when you pull it apart into
    > half-sentences, and reply to bits and pieces that were never intended to
    > represent a complete thought. To clarify what I was trying to say:
    >
    > 1) if you have code like this:
    >
    > class base {}; // note lack of virtual dtor
    > class derived : public base {};
    >
    > base *b = new derived;
    > // ...
    > delete b;
    >
    > You'd get undefined behavior. and:
    >
    > 2) There's absolutely NOTHING you can do in 'derived' to prevent it from
    > being used in that fashion (or many similar ones that cause similar
    > problems).
    >
    > What it comes down to is fairly simple: by using public derivation,
    > you've _promised_ that a derived can be substituted for a base under any
    > and all possible circumstances.


    That seems false: since the language allows public derivation of classes
    without virtual destructor, public inheritance obviously does not _promise_
    that a derived class can be substituted for a base under _any_
    circumstances. If it did, the standard would require the destructor of a
    public base to be virtual. In fact, public inheritance per se does not
    promise anything but the behavior guaranteed by the standard. Any claims
    and connotations beyond the technical meaning of public inheritance are
    part of (local) coding standards and style guides. Those might be more or
    less well-founded and lay out best practices, but they do not define a
    contract for public inheritance. Most importantly, such guidelines are in
    my experience always closely tied to a certain domain or programing
    paradigm, e.g., OO. In a given context, they can be perfectly valid.
    Presented as universal truths about C++ programming, they turn into
    falsehoods rather quickly.

    > The problem arises for the simple reason
    > that this is a lie -- under at least one circumstance (destruction) the
    > substitution leads to undefined behavior.
    >
    > In short, even though you _can_ get away with this as long as you're
    > sufficiently careful about how you use it, it's a lousy idea. Public
    > derivation has a specific meaning.


    (a) The only universal meaning of public inheritance is the one provided by
    the standard, which does not require a virtual destructor.

    (b) In certain contexts (e.g., OO) public inheritance can acquire another
    meaning, e.g., the principle of substitutability that you outlines above.
    Those meanings, however, are context specific.

    > Unless you really mean it, you
    > shouldn't say it by using public derivation. Public derivation from a
    > base class without a virtual dtor asserts a falsehood.


    Nope. See for instance std::unary_function or std::iterator. Inheriting
    publicly from those classes is perfectly fine and does not assert any
    falsehoods. It just happens to be outside the scope of OO design and is
    more closely related to generic programming. In that context, public
    inheritance from base classes without virtual destructor is quite common
    and nobody knowing the corresponding idioms will read public inheritance as
    indicating substitutability in all contexts.


    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Sep 28, 2006
    #16
  17. toton

    toton Guest

    Kai-Uwe Bux wrote:
    > Jerry Coffin wrote:
    >
    > > In article <>,
    > > says...
    > >
    > > [ ... ]
    > >
    > >> No, there's nothing undefined in destroying an object whose type is
    > >> derived from a type that does not have a virtual destructor. You ONLY
    > >> get undefined behavior if you delete such an object through a pointer to
    > >> its base type.

    > >
    > > Well, even I can't figure out what I wrote when you pull it apart into
    > > half-sentences, and reply to bits and pieces that were never intended to
    > > represent a complete thought. To clarify what I was trying to say:
    > >
    > > 1) if you have code like this:
    > >
    > > class base {}; // note lack of virtual dtor
    > > class derived : public base {};
    > >
    > > base *b = new derived;
    > > // ...
    > > delete b;
    > >
    > > You'd get undefined behavior. and:
    > >
    > > 2) There's absolutely NOTHING you can do in 'derived' to prevent it from
    > > being used in that fashion (or many similar ones that cause similar
    > > problems).
    > >
    > > What it comes down to is fairly simple: by using public derivation,
    > > you've _promised_ that a derived can be substituted for a base under any
    > > and all possible circumstances.

    >
    > That seems false: since the language allows public derivation of classes
    > without virtual destructor, public inheritance obviously does not _promise_
    > that a derived class can be substituted for a base under _any_
    > circumstances. If it did, the standard would require the destructor of a
    > public base to be virtual. In fact, public inheritance per se does not
    > promise anything but the behavior guaranteed by the standard. Any claims
    > and connotations beyond the technical meaning of public inheritance are
    > part of (local) coding standards and style guides. Those might be more or
    > less well-founded and lay out best practices, but they do not define a
    > contract for public inheritance. Most importantly, such guidelines are in
    > my experience always closely tied to a certain domain or programing
    > paradigm, e.g., OO. In a given context, they can be perfectly valid.
    > Presented as universal truths about C++ programming, they turn into
    > falsehoods rather quickly.
    >
    > > The problem arises for the simple reason
    > > that this is a lie -- under at least one circumstance (destruction) the
    > > substitution leads to undefined behavior.
    > >
    > > In short, even though you _can_ get away with this as long as you're
    > > sufficiently careful about how you use it, it's a lousy idea. Public
    > > derivation has a specific meaning.

    >
    > (a) The only universal meaning of public inheritance is the one provided by
    > the standard, which does not require a virtual destructor.
    >
    > (b) In certain contexts (e.g., OO) public inheritance can acquire another
    > meaning, e.g., the principle of substitutability that you outlines above.
    > Those meanings, however, are context specific.
    >
    > > Unless you really mean it, you
    > > shouldn't say it by using public derivation. Public derivation from a
    > > base class without a virtual dtor asserts a falsehood.

    >
    > Nope. See for instance std::unary_function or std::iterator. Inheriting
    > publicly from those classes is perfectly fine and does not assert any
    > falsehoods. It just happens to be outside the scope of OO design and is
    > more closely related to generic programming. In that context, public
    > inheritance from base classes without virtual destructor is quite common
    > and nobody knowing the corresponding idioms will read public inheritance as
    > indicating substitutability in all contexts.
    >
    >
    > Best
    >
    > Kai-Uwe Bux

    The best thing I have learned from all these topics is that in C++
    nothing can be prevented from being misused, whatever security you may
    impose. And absolute security is absolutely not possible. C++ can only
    tell you that "it is designed for this purpose, dont use it otherways."
    The whole language and STL is designed that way (one can go out of
    index, iterator can go out of range, iterator dont know their state or
    the container, algo cant remove value from container, auto_ptr can be
    passed by value, typesafe enum's are not enough type safe, destructors
    are not virtual by default, yet it doesn't specify a final keyword to
    prevent inheritance, const function can return non const reference,
    delete can't set the class instance as null, null is simply an int,
    bool gets automatically converted to int, ctor call and function decl
    has same signature, ctor can not be delegated, yet it is allowed as
    syntax, pointer and array are same yet they have same meaning only on
    POD, << thinks it as shift operator, and many other). I really have to
    think of an example where a class can not be misused! .
    So the best thing I can do in my program ( I am the OP ! ) make a
    comment ,"It is designed to use in that way, don't use it other way!" .
    It will be foolish to prevent all such misuses, as there is no way I
    can prevent all or some of them.
    (BTW I had a post in the article for one such misuse(or mistake) and
    ways to prevent is,
    http://groups.google.com/group/comp...c77c5?lnk=gst&q=toton&rnum=2#aecb217bb11c77c5
    but Victor Bazarov hadn't agreed with me, saying "There is no free
    cheese, except in a mouse trap. ". Yesterady I discovered around a
    dozon such trap where "programmers" went just by mistake (not for free
    chese) and got trapped. The result is simple program crash (Silently!
    giving some nonhuman readable message in windows box, and leaving no
    clue for the origin of the error! )
    So, "enjoy programming. If something unfortunate happens (even if it
    destroyes the whole world!) don't blame me. It was NOT designed for
    that purpose! ".
    Cheers
     
    toton, Sep 28, 2006
    #17
  18. toton

    Kai-Uwe Bux Guest

    toton wrote:
    [snip}
    > The best thing I have learned from all these topics is that in C++
    > nothing can be prevented from being misused, whatever security you may
    > impose. And absolute security is absolutely not possible. C++ can only
    > tell you that "it is designed for this purpose, dont use it otherways."
    > The whole language and STL is designed that way (one can go out of
    > index, iterator can go out of range, iterator dont know their state or
    > the container, algo cant remove value from container, auto_ptr can be
    > passed by value, typesafe enum's are not enough type safe, destructors
    > are not virtual by default, yet it doesn't specify a final keyword to
    > prevent inheritance, const function can return non const reference,
    > delete can't set the class instance as null, null is simply an int,
    > bool gets automatically converted to int, ctor call and function decl
    > has same signature, ctor can not be delegated, yet it is allowed as
    > syntax, pointer and array are same yet they have same meaning only on
    > POD, << thinks it as shift operator, and many other). I really have to
    > think of an example where a class can not be misused! .
    > So the best thing I can do in my program ( I am the OP ! ) make a
    > comment ,"It is designed to use in that way, don't use it other way!" .
    > It will be foolish to prevent all such misuses, as there is no way I
    > can prevent all or some of them.

    [snip]

    Well put. There seem to be two schools of thought: one school emphasizes the
    methods of tying the client down so that it cannot go astray; the other
    school emphasizes the goal of designing a useful class and accepts that
    undefined behavior may result from violating the preconditions of the
    specified contract. The STL is an example for the later and, in my opinion,
    establishes a precedence: it is at least not totally out of line to use
    that approach to class design in C++.

    That said, there is almost a continuum of design choices and some are more
    hazardous than others. I would not go out of my way to safeguard against
    all possible misuses, but I would also not propose a design that requires
    each user of the class to read all the fine print to use it for simple
    tasks without running into undefined behavior.

    In the end, I think, each class should come with a set of recommended idioms
    for safe use; and users should know that they have to be careful once they
    depart from the recommended idioms and have to read the actual contracts.


    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Sep 28, 2006
    #18
  19. toton

    Jerry Coffin Guest

    In article <eff94t$g3t$>,
    says...

    [ ... ]

    > That seems false: since the language allows public derivation of classes
    > without virtual destructor, public inheritance obviously does not _promise_
    > that a derived class can be substituted for a base under _any_
    > circumstances.


    You're takin the fact that something is standardized as meaning there
    must be some circumstance under which it should be done, or is
    meaningful, etc?

    While I'm certainly not going to get into a long discussion over it,
    this strikes me as fallacious reasoning. I guess if (for example) you
    insist there's a good time to use gets, you can go ahead and do that. I
    hope you'll forgive me if I pass. While I'll openly admit this isn't
    _as_ dangerous as gets, it's still a bad idea -- there's simply no good
    reason to do it. If you're deriving for the sake of convenience, and
    don't want to allow (for example) pointers/references to your derived
    class to be converted implicitly to pointers/references to the base
    class, you have a choice of private or protected inheritance.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, Sep 28, 2006
    #19
  20. toton

    Jerry Coffin Guest

    In article <effi92$jo1$>,
    says...

    [ ... ]

    > Well put. There seem to be two schools of thought: one school emphasizes the
    > methods of tying the client down so that it cannot go astray; the other
    > school emphasizes the goal of designing a useful class and accepts that
    > undefined behavior may result from violating the preconditions of the
    > specified contract.


    Pardon my being blunt, but this is barely short of complete nonsense.
    Attempting to write your class in a way that it's reasonably safe isn't
    tying the client down.

    A design does not have to encourage its clients to shoot themselves in
    the feet to be useful.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, Sep 28, 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. pmatos
    Replies:
    6
    Views:
    24,028
  2. Replies:
    8
    Views:
    1,984
    Csaba
    Feb 18, 2006
  3. Javier
    Replies:
    2
    Views:
    602
    James Kanze
    Sep 4, 2007
  4. Thomas
    Replies:
    7
    Views:
    336
    Mark Hubbart
    May 23, 2005
  5. Rushikesh Joshi
    Replies:
    0
    Views:
    386
    Rushikesh Joshi
    Jul 10, 2004
Loading...

Share This Page