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