Overloading vs RTTI

C

Chameleon

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 { .......}
}
 
A

Alf P. Steinbach

* 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.
 
D

Daniel T.

Chameleon said:
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.
 
C

Chameleon

What is better if you want upcasting in intermediate classes like below?
Not a meaningful question. Upcasting is implicit in C++. You can use a
static_cast to be clear about it.



No, that's incorrect.



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.

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)
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.
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

rtti 10
class B : virtual public A 3
I/O abstract class suggestions 5
RTTI question 2
Multiple Inheritance vs. Interface 29
templates 2
sizeof and a class with virtual members 5
Virtual destructor 3

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top