need help deriving from the std::list class

Discussion in 'C++' started by JustSomeGuy, Jun 7, 2004.

  1. JustSomeGuy

    JustSomeGuy Guest

    I need to write an new class derived from the list class.
    This class stores data in the list to the disk if an object
    that is added to the list is over 1K in size.

    What methods of the std stl list class must Ioverride in order for this
    to work?
     
    JustSomeGuy, Jun 7, 2004
    #1
    1. Advertising

  2. JustSomeGuy wrote:
    > I need to write an new class derived from the list class.
    > This class stores data in the list to the disk if an object
    > that is added to the list is over 1K in size.
    >
    > What methods of the std stl list class must Ioverride in order for this
    > to work?


    You will not be able to _override_ any members because none of them
    are virtual.

    I recommend private inheritance (or what in OO world is known as
    "implement in terms of" relationship). You will need to implement
    the interface you need and if the objects are smaller than 1K, let
    the underlying std::list handle them in memory, and if they are
    greater, do something else (like retrieve them from disk based on
    the information your underlying list keeps).

    Victor
     
    Victor Bazarov, Jun 7, 2004
    #2
    1. Advertising

  3. JustSomeGuy

    JustSomeGuy Guest

    Victor Bazarov wrote:

    > JustSomeGuy wrote:
    > > I need to write an new class derived from the list class.
    > > This class stores data in the list to the disk if an object
    > > that is added to the list is over 1K in size.
    > >
    > > What methods of the std stl list class must Ioverride in order for this
    > > to work?

    >
    > You will not be able to _override_ any members because none of them
    > are virtual.
    >
    > I recommend private inheritance (or what in OO world is known as
    > "implement in terms of" relationship). You will need to implement
    > the interface you need and if the objects are smaller than 1K, let
    > the underlying std::list handle them in memory, and if they are
    > greater, do something else (like retrieve them from disk based on
    > the information your underlying list keeps).
    >
    > Victor


    I tried this and it works...

    class mylist : public list<int>
    {
    public:
    void push_back(const int & x)
    {
    list<int>::push_back(x);
    }
    };

    Compiles and works .... Has this not overriden push_back?
    What other methods need to be overridden?
     
    JustSomeGuy, Jun 7, 2004
    #3
  4. JustSomeGuy wrote:
    > Victor Bazarov wrote:
    >
    >
    >>JustSomeGuy wrote:
    >>
    >>>I need to write an new class derived from the list class.
    >>>This class stores data in the list to the disk if an object
    >>>that is added to the list is over 1K in size.
    >>>
    >>>What methods of the std stl list class must Ioverride in order for this
    >>>to work?

    >>
    >>You will not be able to _override_ any members because none of them
    >>are virtual.
    >>
    >>I recommend private inheritance (or what in OO world is known as
    >>"implement in terms of" relationship). You will need to implement
    >>the interface you need and if the objects are smaller than 1K, let
    >>the underlying std::list handle them in memory, and if they are
    >>greater, do something else (like retrieve them from disk based on
    >>the information your underlying list keeps).
    >>
    >>Victor

    >
    >
    > I tried this and it works...
    >
    > class mylist : public list<int>
    > {
    > public:
    > void push_back(const int & x)
    > {
    > list<int>::push_back(x);
    > }


    You don't need this for your 'mylist' to function as a list of
    ints. Since you inherit publicly, whenever you call 'push_back'
    for your 'mylist' object, the std::list::push_back is going to
    be called.

    > };
    >
    > Compiles and works .... Has this not overriden push_back?


    No, it has not overridden push_back. Only virtual functions can be
    overridden. What your 'push_back' has done is called _hiding_ of
    the original push_back function.

    > What other methods need to be overridden?


    I guess you don't understand the difference in terms. "Override"
    only applies to virtual functions. Since 'std::list' has none,
    you _cannot_ override anything. No matter what you try, it is not
    going to be "overriding".

    Now, if you don't care for your special list to work polymorphically,
    you shouldn't worry about your inability to override anything. Just
    write the functions you need and then let the std::list do the rest.

    Keep in mind that your list is not going to work polymorphically.
    If by some chance you write

    class MyOwnListOfBigScaryObjects :
    public std::list<MyBigScaryObject> {
    ...
    };

    void foo(std::list<MyBigScaryObject>& mylist) {
    mylist.push_back(someScaryObject);
    }

    that even if you define your own push_back member in your class,
    it will NOT be called. I am not trying to talk you out of deriving
    from 'std::list', just warning you of potential pitfalls.

    Victor
     
    Victor Bazarov, Jun 7, 2004
    #4
  5. JustSomeGuy

    JustSomeGuy Guest

    Victor Bazarov wrote:

    > JustSomeGuy wrote:
    > > Victor Bazarov wrote:
    > >
    > >
    > >>JustSomeGuy wrote:
    > >>
    > >>>I need to write an new class derived from the list class.
    > >>>This class stores data in the list to the disk if an object
    > >>>that is added to the list is over 1K in size.
    > >>>
    > >>>What methods of the std stl list class must Ioverride in order for this
    > >>>to work?
    > >>
    > >>You will not be able to _override_ any members because none of them
    > >>are virtual.
    > >>
    > >>I recommend private inheritance (or what in OO world is known as
    > >>"implement in terms of" relationship). You will need to implement
    > >>the interface you need and if the objects are smaller than 1K, let
    > >>the underlying std::list handle them in memory, and if they are
    > >>greater, do something else (like retrieve them from disk based on
    > >>the information your underlying list keeps).
    > >>
    > >>Victor

    > >
    > >
    > > I tried this and it works...
    > >
    > > class mylist : public list<int>
    > > {
    > > public:
    > > void push_back(const int & x)
    > > {
    > > list<int>::push_back(x);
    > > }

    >
    > You don't need this for your 'mylist' to function as a list of
    > ints. Since you inherit publicly, whenever you call 'push_back'
    > for your 'mylist' object, the std::list::push_back is going to
    > be called.
    >
    > > };
    > >
    > > Compiles and works .... Has this not overriden push_back?

    >
    > No, it has not overridden push_back. Only virtual functions can be
    > overridden. What your 'push_back' has done is called _hiding_ of
    > the original push_back function.
    >


    Ok perhaps this is just a question of symantics then overridding vs hinding...



    >
    > > What other methods need to be overridden?

    >
    > I guess you don't understand the difference in terms. "Override"
    > only applies to virtual functions. Since 'std::list' has none,
    > you _cannot_ override anything. No matter what you try, it is not
    > going to be "overriding".
    >
    > Now, if you don't care for your special list to work polymorphically,
    > you shouldn't worry about your inability to override anything. Just
    > write the functions you need and then let the std::list do the rest.
    >


    Ok what functions do I 'need' to write? I think that is the original
    question.
    Yes they are very big objects on average the list grows to 40 Mega-Bytes.

    >
    > Keep in mind that your list is not going to work polymorphically.
    > If by some chance you write
    >


    Are you saying that no one will be able to treat my class as a stl sdt::list?


    >
    > class MyOwnListOfBigScaryObjects :
    > public std::list<MyBigScaryObject> {
    > ...
    > };
    >
    > void foo(std::list<MyBigScaryObject>& mylist) {
    > mylist.push_back(someScaryObject);
    > }
    >
    > that even if you define your own push_back member in your class,
    > it will NOT be called. I am not trying to talk you out of deriving
    > from 'std::list', just warning you of potential pitfalls.
    >


    I apprieate the warning... :)



    >
    > Victor
     
    JustSomeGuy, Jun 7, 2004
    #5
  6. JustSomeGuy wrote:
    > Victor Bazarov wrote:
    >
    >
    >>JustSomeGuy wrote:
    >>
    >>>Victor Bazarov wrote:
    >>>
    >>>
    >>>
    >>>>JustSomeGuy wrote:
    >>>>
    >>>>
    >>>>>I need to write an new class derived from the list class.
    >>>>>This class stores data in the list to the disk if an object
    >>>>>that is added to the list is over 1K in size.
    >>>>>
    >>>>>What methods of the std stl list class must Ioverride in order for this
    >>>>>to work?
    >>>>
    >>>>You will not be able to _override_ any members because none of them
    >>>>are virtual.
    >>>>
    >>>>I recommend private inheritance (or what in OO world is known as
    >>>>"implement in terms of" relationship). You will need to implement
    >>>>the interface you need and if the objects are smaller than 1K, let
    >>>>the underlying std::list handle them in memory, and if they are
    >>>>greater, do something else (like retrieve them from disk based on
    >>>>the information your underlying list keeps).
    >>>>
    >>>>Victor
    >>>
    >>>
    >>>I tried this and it works...
    >>>
    >>>class mylist : public list<int>
    >>>{
    >>>public:
    >>> void push_back(const int & x)
    >>> {
    >>> list<int>::push_back(x);
    >>> }

    >>
    >>You don't need this for your 'mylist' to function as a list of
    >>ints. Since you inherit publicly, whenever you call 'push_back'
    >>for your 'mylist' object, the std::list::push_back is going to
    >>be called.
    >>
    >>
    >>>};
    >>>
    >>>Compiles and works .... Has this not overriden push_back?

    >>
    >>No, it has not overridden push_back. Only virtual functions can be
    >>overridden. What your 'push_back' has done is called _hiding_ of
    >>the original push_back function.
    >>

    >
    >
    > Ok perhaps this is just a question of symantics then overridding vs hinding...


    Semantics is integral part of any language. English or C++. It is
    important to understand the difference even if only to ignore it.

    >>>What other methods need to be overridden?

    >>
    >>I guess you don't understand the difference in terms. "Override"
    >>only applies to virtual functions. Since 'std::list' has none,
    >>you _cannot_ override anything. No matter what you try, it is not
    >>going to be "overriding".
    >>
    >>Now, if you don't care for your special list to work polymorphically,
    >>you shouldn't worry about your inability to override anything. Just
    >>write the functions you need and then let the std::list do the rest.
    >>

    >
    >
    > Ok what functions do I 'need' to write?


    How should *I* know? You're going to be using the class, not I.

    > I think that is the original
    > question.


    But who except you can answer this?

    If you want your class to be used by standard algorithms for searching,
    sorting, etc., you need to provide iterators to the contents of your
    collection. I strongly recommend a good book on the standard library
    (Nicolai Josuttis wrote the best so far). The margins of this posting
    are not wide enough to accommodate a decent explanation on how to write
    your own library-compliant container.

    > Yes they are very big objects on average the list grows to 40 Mega-Bytes.


    I believe you.

    >>Keep in mind that your list is not going to work polymorphically.
    >>If by some chance you write
    >>

    >
    >
    > Are you saying that no one will be able to treat my class as a stl sdt::list?


    What do you mean by "treat" your class as std::list? You cannot pass
    a pointer or a reference to your class to another function that expects
    a pointer or a reference to std::list, and have that other function call
    member functions of _your_ class. If the functions are not virtual (and
    they are not in std::list), they are not going to be resolved to your
    "variations".

    OTOH, if the other function is expecting _your_ list (either as a pointer
    or as a reference, don't try passing it by value), then everything should
    be fine.

    In general you should remember that if you want the rest of the world to
    be able to think that your class is just like std::list, your class must
    have "is-a" relationship with std::list. However, if you want some of
    std::list behaviour substituted for your own in certain conditions, you
    need polymorphism, and none of standard containers provide that. That's
    why I said that you'd be better off reimplementing everything you need
    while deriving from std::list privately. At least then you will be able
    to prevent people from passing your wonderful class into functions that
    expect std::list (private inheritance disables implicit conversion to
    base).

    >> class MyOwnListOfBigScaryObjects :
    >> public std::list<MyBigScaryObject> {
    >> ...
    >> };
    >>
    >> void foo(std::list<MyBigScaryObject>& mylist) {
    >> mylist.push_back(someScaryObject);
    >> }
    >>
    >>that even if you define your own push_back member in your class,
    >>it will NOT be called. I am not trying to talk you out of deriving
    >>from 'std::list', just warning you of potential pitfalls.
    >>

    >
    >
    > I apprieate the warning... :)


    You're welcome.
     
    Victor Bazarov, Jun 7, 2004
    #6
  7. JustSomeGuy <> wrote in message news:<>...
    > I need to write an new class derived from the list class.
    > This class stores data in the list to the disk if an object
    > that is added to the list is over 1K in size.
    >
    > What methods of the std stl list class must Ioverride in order for this
    > to work?


    std::list is not a class, it is a template. When you instantiate it by
    providing arguments to the template parameters, you get a class.

    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    To iterate is human, to recurse divine.
    -L. Peter Deutsch
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     
    Prateek R Karandikar, Jun 9, 2004
    #7
  8. JustSomeGuy

    tom_usenet Guest

    On Mon, 07 Jun 2004 13:40:03 -0600, JustSomeGuy <>
    wrote:

    >I need to write an new class derived from the list class.
    >This class stores data in the list to the disk if an object
    >that is added to the list is over 1K in size.
    >
    >What methods of the std stl list class must Ioverride in order for this
    >to work?


    I would suggest not inheriting from std::list at all, but providing
    your own limited list interface, where you can intercept the "size" of
    intercepted objects more easily. With std::list, there are many ways
    of adding elements to the list, and many of them can't be intercepted.
    e.g.

    *mylist.begin() = myenormousobject;
    //your list type never gets to intercept that
    or:
    std::list& l = mylist;
    l.push_back(myenormousobject);
    //your list type never gets to intercept that

    Instead, provide a limited interface that gives you the control you
    need:

    class MyList
    {
    std::list<MyObject> m_list; //or use private inheritence
    public:
    const_iterator begin() const;
    const_iterator end() const;
    //don't provide non-const iterators.

    void push_back(MyObject const& object);

    //add a few more functions, but how many do you need?
    };

    Tom
    --
    C++ FAQ: http://www.parashift.com/c -faq-lite/
    C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
     
    tom_usenet, Jun 10, 2004
    #8
  9. JustSomeGuy <> wrote in message news:<>...
    > I need to write an new class derived from the list class.
    > This class stores data in the list to the disk if an object
    > that is added to the list is over 1K in size.
    >
    > What methods of the std stl list class must Ioverride in order for this
    > to work?


    Actually, you probably shouldn't try to override list. Instead, you should
    proxy the class you put in.

    E.g. instead of
    std::list<MyClass> list;
    you write
    std::list<MyClassProxy> list;

    Example definitions for MyClass and MyClassProxy:

    class MyClass {
    std::string sometimes_big;
    public:
    std::string get() const;
    }


    class MyClassProxy {
    bool in_file;
    std::string filename_or_smallstring;
    public:
    MyClassProxy( MyClass const& mc ) {
    filename_or_smallstring = mc.get();
    in_file = false;
    if( filename_or_smallstring.size() >= 1024 )
    {
    filename_or_smallstring = save_to_newfile(filename_or_smallstring);
    in_file = true;
    }
    }
    std::string get() const {
    if(infile)
    return read_from_file(filename_or_smallstring);
    else
    return filename_or_smallstring;
    }
    operator MyClass() const { return MyClass(get()); }
    private:
    std::string save_to_newfile( std::string const& s ); // returns filename
    std::string read_from_file ( std::string const& filename );
    };
     
    Michiel Salters, Jun 10, 2004
    #9
    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. Noah Roberts

    deriving from std::exception

    Noah Roberts, Jul 31, 2003, in forum: C++
    Replies:
    3
    Views:
    4,953
    Greg P.
    Aug 1, 2003
  2. Stefan Pantos
    Replies:
    2
    Views:
    3,103
    Derek
    May 20, 2004
  3. Guest
    Replies:
    3
    Views:
    716
    John Harrison
    Aug 8, 2004
  4. Nick Keighley

    deriving from std::runtime_error

    Nick Keighley, Aug 6, 2008, in forum: C++
    Replies:
    2
    Views:
    600
  5. Urs Thuermann
    Replies:
    11
    Views:
    712
    Balog Pal
    Jul 9, 2011
Loading...

Share This Page