Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Overloading vs RTTI

Reply
Thread Tools

Overloading vs RTTI

 
 
Chameleon
Guest
Posts: n/a
 
      01-29-2007
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(SeekableInputStrea m &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 { .......}
}
 
Reply With Quote
 
 
 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      01-29-2007
* 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(SeekableInputStrea m &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?
 
Reply With Quote
 
 
 
 
Daniel T.
Guest
Posts: n/a
 
      01-29-2007
Chameleon <(E-Mail Removed)> 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(SeekableInputStrea m &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 { .......}
> }

 
Reply With Quote
 
Chameleon
Guest
Posts: n/a
 
      01-29-2007
>> 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(SeekableInputStrea m &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.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
RE: Overloading __init__ & Function overloading Iyer, Prasad C Python 4 09-30-2005 08:01 PM
Re: Overloading __init__ & Function overloading Fredrik Lundh Python 0 09-30-2005 03:59 PM
Overloading __init__ & Function overloading Iyer, Prasad C Python 3 09-30-2005 02:17 PM
Re: Overloading __init__ & Function overloading Steve Holden Python 0 09-30-2005 01:58 PM
Re: Overloading __init__ & Function overloading Fredrik Lundh Python 0 09-30-2005 01:53 PM



Advertisments