Overloading vs RTTI

Discussion in 'C++' started by Chameleon, Jan 29, 2007.

  1. Chameleon

    Chameleon Guest

    What is better if you want upcasting in intermediate classes like below?
    Multiple Inheritance and Overloading or simply RTTI?
    RTTI wants time but MI and Overloading create big objects
    (because of virtual) and finally they need time too to access objects
    inside big object.

    (Examples looks complicated but are very simple)

    Paradigm #1: MI & Overloading
    =============================

    //--------------- base classes
    class Position { public: virtual size_t tell() = 0; };
    class InputStream : virtual public Position { public: virtual size_t
    read(const void *base, size_t size) = 0; };
    class OutputStream : virtual public Position { public: virtual size_t
    write(const void *base, size_t size) = 0; };
    class Seekable { public: virtual size_t size() = 0;
    public: virtual void seek(size_t position) = 0; };
    //--------------- intermediate classes
    class SeekableInputStream : public InputStream, virtual public Seekable {};
    class SeekableOutputStream : public OutputStream, virtual public
    Seekable {};
    class SeekableStream : virtual public SeekableInputStream, virtual
    public SeekableOutputStream {};
    //--------------- most derived and fully implemented classes
    class FileInputStream : public virtual SeekableInputStream { ..... };
    class FileOutputStream : public virtual SeekableOutputStream { ..... };
    class FileStream : public FileInputStream, public FileOutputStream,
    virtual public SeekableStream { ...... };
    //--------------- overloaded functions
    void ZipFileSystem::attachFileSystem(SeekableInputStream &sis);
    void ZipFileSystem::attachFileSystem(SeekableStream &ss);


    Paradigm #2: RTTI
    =================

    //--------------- base classes
    class Position { public: virtual size_t tell() = 0; };
    class InputStream { public: virtual size_t read(const void *base, size_t
    size) = 0; };
    class OutputStream { public: virtual size_t write(const void *base,
    size_t size) = 0; };
    class Seekable { public: virtual size_t size() = 0;
    public: virtual void seek(size_t position) = 0; };
    //--------------- there are no intermediate classes
    //--------------- most derived and fully implemented classes
    class FileInputStream : virtual public Position, virtual public
    Seekable, public InputStream { ..... };
    class FileOutputStream : virtual public Position, virtual public
    Seekable, public OutputStream { ..... };
    class FileStream : public FileInputStream, public FileOutputStream {
    ....... };
    //--------------- overloaded functions
    void ZipFileSystem::attachFileSystem(Seekable &s)
    {
    // by definition:
    // Seekable object CONTAINS Position object AND (InputStream object OR
    OutputStream object)
    if (!dynamic_cast<InputStream*(&s)) throw EXCEPTION; // if contains
    only OutputStream
    if (dynamic_cast<OutputStream*(&s)) { ...... } else { .......}
    }
     
    Chameleon, Jan 29, 2007
    #1
    1. Advertising

  2. * Chameleon:
    > What is better if you want upcasting in intermediate classes like below?
    > Multiple Inheritance and Overloading or simply RTTI?


    Not a meaningful question. Upcasting is implicit in C++. You can use a
    static_cast to be clear about it.


    > RTTI wants time but MI and Overloading create big objects
    > (because of virtual)


    No, that's incorrect.


    > and finally they need time too to access objects
    > inside big object.


    No.


    > (Examples looks complicated but are very simple)
    >
    > Paradigm #1: MI & Overloading
    > =============================
    >
    > //--------------- base classes
    > class Position { public: virtual size_t tell() = 0; };
    > class InputStream : virtual public Position { public: virtual size_t
    > read(const void *base, size_t size) = 0; };
    > class OutputStream : virtual public Position { public: virtual size_t
    > write(const void *base, size_t size) = 0; };
    > class Seekable { public: virtual size_t size() = 0;
    > public: virtual void seek(size_t position) = 0; };


    Is your intent really that an InputStream *is* a Position?


    > //--------------- intermediate classes
    > class SeekableInputStream : public InputStream, virtual public Seekable {};
    > class SeekableOutputStream : public OutputStream, virtual public
    > Seekable {};
    > class SeekableStream : virtual public SeekableInputStream, virtual
    > public SeekableOutputStream {};
    > //--------------- most derived and fully implemented classes
    > class FileInputStream : public virtual SeekableInputStream { ..... };
    > class FileOutputStream : public virtual SeekableOutputStream { ..... };
    > class FileStream : public FileInputStream, public FileOutputStream,
    > virtual public SeekableStream { ...... };
    > //--------------- overloaded functions
    > void ZipFileSystem::attachFileSystem(SeekableInputStream &sis);
    > void ZipFileSystem::attachFileSystem(SeekableStream &ss);


    Not sure what you're trying to do but it's a mess. Perhaps you've
    modelled this on standard iostream and inherited the mess from there?
    Offer interfaces rather than let a stream really be two streams.



    > Paradigm #2: RTTI
    > =================
    >
    > //--------------- base classes
    > class Position { public: virtual size_t tell() = 0; };
    > class InputStream { public: virtual size_t read(const void *base, size_t
    > size) = 0; };
    > class OutputStream { public: virtual size_t write(const void *base,
    > size_t size) = 0; };
    > class Seekable { public: virtual size_t size() = 0;
    > public: virtual void seek(size_t position) = 0; };
    > //--------------- there are no intermediate classes
    > //--------------- most derived and fully implemented classes
    > class FileInputStream : virtual public Position, virtual public
    > Seekable, public InputStream { ..... };
    > class FileOutputStream : virtual public Position, virtual public
    > Seekable, public OutputStream { ..... };
    > class FileStream : public FileInputStream, public FileOutputStream {
    > ...... };


    Again, are you sure that e.g. a FileInputStream *is* a Position?

    And again, are you sure you want one logical stream to really be two
    streams?


    > //--------------- overloaded functions
    > void ZipFileSystem::attachFileSystem(Seekable &s)
    > {
    > // by definition:
    > // Seekable object CONTAINS Position object AND (InputStream object OR
    > OutputStream object)


    ?


    > if (!dynamic_cast<InputStream*(&s)) throw EXCEPTION; // if contains
    > only OutputStream
    > if (dynamic_cast<OutputStream*(&s)) { ...... } else { .......}
    > }


    Evidently you want 'attachFileSystem' to behave differently depending on
    whether it's dealing with an input stream or an output stream. That
    means you're really dealing with two different functions. So just make
    them two different functions.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    sA: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Jan 29, 2007
    #2
    1. Advertising

  3. Chameleon

    Daniel T. Guest

    Chameleon <> wrote:

    > What is better if you want upcasting in intermediate classes like below?
    > Multiple Inheritance and Overloading or simply RTTI?


    Given only the two examples to choose from, I'd go with example 1. I
    don't like either very much though.

    > (Examples looks complicated but are very simple)


    When simple stuff looks complicated, then there is probably something
    wrong. Of course idiomatic use of newlines and indentation would
    probably help quite a bit.

    > Paradigm #1: MI & Overloading
    > =============================
    >
    > //--------------- base classes
    > class Position { public: virtual size_t tell() = 0; };
    > class InputStream : virtual public Position { public: virtual size_t
    > read(const void *base, size_t size) = 0; };
    > class OutputStream : virtual public Position { public: virtual size_t
    > write(const void *base, size_t size) = 0; };
    > class Seekable { public: virtual size_t size() = 0;
    > public: virtual void seek(size_t position) = 0; };
    > //--------------- intermediate classes
    > class SeekableInputStream : public InputStream, virtual public Seekable {};
    > class SeekableOutputStream : public OutputStream, virtual public
    > Seekable {};
    > class SeekableStream : virtual public SeekableInputStream, virtual
    > public SeekableOutputStream {};
    > //--------------- most derived and fully implemented classes
    > class FileInputStream : public virtual SeekableInputStream { ..... };
    > class FileOutputStream : public virtual SeekableOutputStream { ..... };
    > class FileStream : public FileInputStream, public FileOutputStream,
    > virtual public SeekableStream { ...... };
    > //--------------- overloaded functions
    > void ZipFileSystem::attachFileSystem(SeekableInputStream &sis);
    > void ZipFileSystem::attachFileSystem(SeekableStream &ss);
    >
    >
    > Paradigm #2: RTTI
    > =================
    >
    > //--------------- base classes
    > class Position { public: virtual size_t tell() = 0; };
    > class InputStream { public: virtual size_t read(const void *base, size_t
    > size) = 0; };
    > class OutputStream { public: virtual size_t write(const void *base,
    > size_t size) = 0; };
    > class Seekable { public: virtual size_t size() = 0;
    > public: virtual void seek(size_t position) = 0; };
    > //--------------- there are no intermediate classes
    > //--------------- most derived and fully implemented classes
    > class FileInputStream : virtual public Position, virtual public
    > Seekable, public InputStream { ..... };
    > class FileOutputStream : virtual public Position, virtual public
    > Seekable, public OutputStream { ..... };
    > class FileStream : public FileInputStream, public FileOutputStream {
    > ...... };
    > //--------------- overloaded functions
    > void ZipFileSystem::attachFileSystem(Seekable &s)
    > {
    > // by definition:
    > // Seekable object CONTAINS Position object AND (InputStream object OR
    > OutputStream object)
    > if (!dynamic_cast<InputStream*(&s)) throw EXCEPTION; // if contains
    > only OutputStream
    > if (dynamic_cast<OutputStream*(&s)) { ...... } else { .......}
    > }
     
    Daniel T., Jan 29, 2007
    #3
  4. Chameleon

    Chameleon Guest

    >> What is better if you want upcasting in intermediate classes like below?
    >> Multiple Inheritance and Overloading or simply RTTI?

    >
    > Not a meaningful question. Upcasting is implicit in C++. You can use a
    > static_cast to be clear about it.
    >
    >
    >> RTTI wants time but MI and Overloading create big objects
    >> (because of virtual)

    >
    > No, that's incorrect.
    >
    >
    >> and finally they need time too to access objects
    >> inside big object.

    >
    > No.
    >
    >
    >> (Examples looks complicated but are very simple)
    >>
    >> Paradigm #1: MI & Overloading
    >> =============================
    >>
    >> //--------------- base classes
    >> class Position { public: virtual size_t tell() = 0; };
    >> class InputStream : virtual public Position { public: virtual size_t
    >> read(const void *base, size_t size) = 0; };
    >> class OutputStream : virtual public Position { public: virtual size_t
    >> write(const void *base, size_t size) = 0; };
    >> class Seekable { public: virtual size_t size() = 0;
    >> public: virtual void seek(size_t position) = 0; };

    >
    > Is your intent really that an InputStream *is* a Position?


    Position is the interface of giving the stream pointer's position. Any
    stream (InputStream, OutputStream and derived) want to implement this.
    No. Stream is not a Position but contains the complete functionality of
    Position.


    >> //--------------- intermediate classes
    >> class SeekableInputStream : public InputStream, virtual public
    >> Seekable {};
    >> class SeekableOutputStream : public OutputStream, virtual public
    >> Seekable {};
    >> class SeekableStream : virtual public SeekableInputStream, virtual
    >> public SeekableOutputStream {};
    >> //--------------- most derived and fully implemented classes
    >> class FileInputStream : public virtual SeekableInputStream { ..... };
    >> class FileOutputStream : public virtual SeekableOutputStream { ..... };
    >> class FileStream : public FileInputStream, public FileOutputStream,
    >> virtual public SeekableStream { ...... };
    >> //--------------- overloaded functions
    >> void ZipFileSystem::attachFileSystem(SeekableInputStream &sis);
    >> void ZipFileSystem::attachFileSystem(SeekableStream &ss);

    >
    > Not sure what you're trying to do but it's a mess. Perhaps you've
    > modelled this on standard iostream and inherited the mess from there?
    > Offer interfaces rather than let a stream really be two streams.


    No. Classes are exactly as is in sample code. There are more most
    derived classes although. (like Bz2DecompressInputStream)

    >> Paradigm #2: RTTI
    >> =================
    >>
    >> //--------------- base classes
    >> class Position { public: virtual size_t tell() = 0; };
    >> class InputStream { public: virtual size_t read(const void *base, size_t
    >> size) = 0; };
    >> class OutputStream { public: virtual size_t write(const void *base,
    >> size_t size) = 0; };
    >> class Seekable { public: virtual size_t size() = 0;
    >> public: virtual void seek(size_t position) = 0; };
    >> //--------------- there are no intermediate classes
    >> //--------------- most derived and fully implemented classes
    >> class FileInputStream : virtual public Position, virtual public
    >> Seekable, public InputStream { ..... };
    >> class FileOutputStream : virtual public Position, virtual public
    >> Seekable, public OutputStream { ..... };
    >> class FileStream : public FileInputStream, public FileOutputStream {
    >> ...... };

    >
    > Again, are you sure that e.g. a FileInputStream *is* a Position?


    No. Contains a Position.

    > And again, are you sure you want one logical stream to really be two
    > streams?


    Yes. With this, in a function with an OutputStream parameter, I can pass
    an OutputStream, a SeekableOutputStream, a SeekableStream etc because
    all of them contain the OutputStream functionality.
    I am trying the streams contain the most possible shared code.

    >> //--------------- overloaded functions
    >> void ZipFileSystem::attachFileSystem(Seekable &s)
    >> {
    >> // by definition:
    >> // Seekable object CONTAINS Position object AND (InputStream
    >> object OR
    >> OutputStream object)

    >
    > ?
    >
    >
    >> if (!dynamic_cast<InputStream*(&s)) throw EXCEPTION; // if contains
    >> only OutputStream
    >> if (dynamic_cast<OutputStream*(&s)) { ...... } else { .......}
    >> }

    >
    > Evidently you want 'attachFileSystem' to behave differently depending on
    > whether it's dealing with an input stream or an output stream. That
    > means you're really dealing with two different functions. So just make
    > them two different functions.


    I take the point. Thanks.
     
    Chameleon, Jan 29, 2007
    #4
    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. Iyer, Prasad C

    Overloading __init__ & Function overloading

    Iyer, Prasad C, Sep 30, 2005, in forum: Python
    Replies:
    3
    Views:
    6,437
    Fredrik Lundh
    Sep 30, 2005
  2. Fredrik Lundh
    Replies:
    0
    Views:
    462
    Fredrik Lundh
    Sep 30, 2005
  3. Steve Holden
    Replies:
    0
    Views:
    445
    Steve Holden
    Sep 30, 2005
  4. Iyer, Prasad C
    Replies:
    4
    Views:
    595
    John J. Lee
    Sep 30, 2005
  5. Fredrik Lundh
    Replies:
    0
    Views:
    414
    Fredrik Lundh
    Sep 30, 2005
Loading...

Share This Page