justanotherguy63@yahoo.com wrote:[color=blue]
> I am designing an application where to preserve the hierachy and for
> code substitability, I need to pass an array of derived class object in
> place of an array of base class object. Since I am using vector
> class(STL), the compiler does not allow me to do this.[/color]
Object orientation meets reality... There are actually languages
where something like this is supported but it is inherently broken:
An array of derived IS-NOT-A array of base, i.e. passing an array of
derived where an array of base is expected is a violation of the
Liskov Substition Principle: In an array of base, you should be able
to place a base object. Of course, this would mean that an array of
derived actually holds both derived and base objects or possibly
other derived objects which is not possible and thus proving that
it is a violation of LSP. Since I have seen answers trying to
address the problem by using pointers, note that the same LSP
violation applies to arrays of pointers.
OK, after addressing why it is conceptually nonsense to treat an
array of derived as an array of base, lets have a look why it does
not work in C++ from a technical point of view: in C++ the expression
'a[i]' is effectively just '*(a + i)' where 'a + i' just computes
the address by adding 'i * sizeof(a[0])' to 'a'. Since generally
'sizeof(Base) != sizeof(Derived)', this gives a technical reason why
you cannot access an array of derived as an array of base, even after
forcing it through a reinterpret_cast'. The same applies, of course,
to data structures internally using arrays like 'std::vector' or
'std::deque'.
[color=blue]
> I do realize there is a pitfall in this approach(size of arrays not
> matching etc), but I wonder how to get around this problem. I have a
> class hierachy with abstract base class and all I wonder why the
> principle of passing a derived class reference in place of base class
> is not extended to arrays. After all, we are making the code more
> substitutable right? How do we achieve substitutability in this case?[/color]
Do you really need the class hierarchy or are you using it because
it "always sounded crisp"? If the latter, throw it out as fast as you
can! Object orientation has some merit but it is in no way a panacea
and it is grossly overused (well, at least the dynamic polymorphism
stuff is; I'm using encapsulation all the time but that is not the
central theme assumed as object orientation by most people).
Assuming you really need dynamic polymorphism for the stuff you do
(which is in my experience actually relatively unlikely; there are
a few uses but much less than is typically assumed), here is what
you might be able to do: Rather than passing the array directly, you
could pass a reference to a decorator whose derived classes are
actually templates created from your array, e.g.
| *template <typename T>
| *class array_base
| *{
| *public:
| * *virtual ~array_base();
| * *virtual std::size_t size() const * * * * * * *= 0;
| * *virtual T& * * * * *operator[](int idx) * * * = 0;
| * *virtual T const& * *operator[](int idx) const = 0;
| * *// possibly other operations, most likely none adding elements
| *};
| *template <typename T, typename Cont>
| *class array: public array_base<T>
| *{
| *public:
| * *array(Cont& c): m_cont(c) {}
| *private:
| * *std::size_t size() const { return m_cont.size(); }
| * *T& * * * * *operator[](int idx) * * * { return m_cont[idx]; }
| * *T const& * *operator[](int idx) const { return m_cont[idx]; }
| * *Cont& m_cont;
| *};
You would now implement your dynamic generic operations in terms of
'array_base<Base>&' where 'Base' is your base class and pass objects
of type 'array<Base, Cont>' to it.
Generally, something like this unnecessary burdonsome and
inconvenient. If you merely need genericity but no dynamic
polymorphism, you should probably apply generic techniques as in
the STL: you pass appropriate iterators to suitably parameterized
function templates.
[color=blue]
> To me at least, not having to make needless changes to code and having
> the ability to sort things out dynamically using inheritance has always
> sounded crisp.[/color]
OO sounds really nice, doesn't it. It would be cool if it could
live up to, say, 10% of its promises...
[color=blue]
> Also, does this problem mean there is some deficiency in my application
> design?[/color]
I'd guess "probably". Since you didn't mention your requirements
it is impossible to tell, though. There are uses where you need
dynamic polymorphism but these are rarer than many people think.
Typically, it is easy to tell which approach is indicated: the
one which is simplest and solves the problem :-)
--
<mailto:dietmar_kuehl@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.contendix.com> - Software Development & Consulting