473,708 Members | 2,455 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Passing derived class object array in place of base class object array

Hi,

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.

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 substitutabilit y in this case?
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.

Also, does this problem mean there is some deficiency in my application
design? Any light you throw on this will be greatly appreciated.
Thanks.
justanotherguy

Jul 22 '05 #1
9 4798
ju************* *@yahoo.com wrote:
Hi,

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.

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 substitutabilit y in this case?
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.

Also, does this problem mean there is some deficiency in my application design? Any light you throw on this will be greatly appreciated.
Thanks.
justanotherguy


Why do you not write a small wrapper class around std::vector?

#include <vector>
#include <memory>

class BaseVector {
public:
typedef std::vector<Bas e*> Vector;
public:
// delete contents of vector_.
~BaseVector();
// copy contents of vector_.
BaseVector(cons t BaseVector& rhs);
// copy contents of vector_.
BaseVector& operator=(const BaseVector& rhs);
public: // adding elements
// add an element, copying, see 1) below
void push_back(const Base& base);
// add an element: takes ownership.
void push_back(std:: auto_ptr<Base*> base);
public: // wrappers to vector_ as needed, e.g.:
// number of elements
Vector::size_ty pe size() const;
private:
Vector vector_;
};

1) requires something like:
class Base {
public:
// create a copy of the class.
std::auto_ptr<B ase*> clone() const = 0;
};

Stephan Brönnimann
br****@osb-systems.com
Open source rating and billing engine for communication networks.

P.S. I'm posting via Google: with their new beta version I can't get a
proper
indentation in the preview!?

Jul 22 '05 #2
On 2 Dec 2004 00:51:28 -0800, ju************* *@yahoo.com wrote:
Hi,

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.
I think with "business" entities, the kind of class that has a base
class, you would typically store a vector of pointers. e.g.
std::vector<Der ived*> or std::vector<sha red_ptr<Derived > >. Usually
such entities aren't copyable, so can't be placed in containers
directly. In any case, this level of indirection is useful.
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
substitutabl e right? How do we achieve substitutabilit y in this case?
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.
If you have a std::vector<Der ived*>, you can create a vector<Base*>
simply with:
std::vector<Bas e*>(v.begin(), v.end());
and pass that. It will only involve a single memory allocation (even
in the smart pointer case), which isn't bad.

It efficiency is a problem, then you do have an alternative that
should work for single, non-virtual inheritence (where the address of
the derived object usually matches that of the base one). It is
undefined behaviour though, so only use it if profiling identifies a
problem:

std::vector<Bas e*> const& vb =
reinterpret_cas t<std::vector<B ase*>&>(vd);
Also, does this problem mean there is some deficiency in my application
design? Any light you throw on this will be greatly appreciated.


Well, you might find that you can get away with having a
std::vector<Bas e*> all the time anyway, and do away with the
vector<Derived* >.

Tom
Jul 22 '05 #3
test

Jul 22 '05 #4
ju************* *@yahoo.com wrote:
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.
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_cas t'. The same applies, of course,
to data structures internally using arrays like 'std::vector' or
'std::deque'.
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 substitutabilit y in this case?
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<Bas e>&' 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.
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.
OO sounds really nice, doesn't it. It would be cool if it could
live up to, say, 10% of its promises...
Also, does this problem mean there is some deficiency in my application
design?


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:di***** ******@yahoo.co m> <http://www.dietmar-kuehl.de/>
<http://www.contendix.c om> - Software Development & Consulting

Jul 22 '05 #5
<ju************ **@yahoo.com> wrote in message
news:11******** **************@ f14g2000cwb.goo glegroups.com.. .
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.


Right. In general, a container of derived objects cannot substitute for a
container of base objects, because what happens if you try to put a base
object into the container?

In other words: D is derived from B, and you have a function that expects a
vector<B>. What happens if you were allowed to give it a vector<D> and it
tried to put a B into the vector?
Jul 22 '05 #6
On 3 Dec 2004 05:28:21 GMT, Dietmar Kuehl <di***********@ yahoo.com>
wrote:
ju************ **@yahoo.com wrote:
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.
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.


OTOH, a container of non-const derived IS-A const container of
non-const base (but be careful of slicing if assignment isn't
disabled). A container of non-const derived* IS-A const container of
non-const base* const. The language doesn't support this though. Those
languages that do support using an array of derived as an array of
base don't support "const", and are thus saddled with an error prone
runtime check to prevent elements from being illegally modified.
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 substitutabilit y in this case?


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


Polymorphism does have a place, but it often used at the wrong
granularity. Concrete objects parametrised with various
pointer-to-base objects (such as the iostreams classes parametrised
with a streambuf and locale facets) are often useful, but often people
make the original object an interface instead (e.g to use the
iostreams example, by putting the output behaviour and formatting
behaviour all in one class). Abstract base classes should generally
only do one job.
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<Ba se>&' where 'Base' is your base class and pass objects
of type 'array<Base, Cont>' to it.


A specialization for (smart) pointer types (returning non-references
for operator[]) would be useful I think.

Tom
Jul 22 '05 #7
* Andrew Koenig:

In general, a container of derived objects cannot substitute for a
container of base objects, because what happens if you try to put a base
object into the container?


Is there any way in C++ to create a smartpointer that acts like a Java
reference?

Assuming there isn't (which is what I believe), is there any way the
language could be, er, "improved", so that that would be possible?

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #8
Thanks guys for your views. There were some very interesting and
innovative ways to work around the problem in the replies.Sorry for
getting back late because I had a bout of asthma and c++ was far from
my mind for the past few days.

Anyways, I did some soul searching about the design of the application
and the one point that came to my mind was what one friend of mine
used to say: "If it is too hard then maybe that is not the way it
should be". The problem was that there were two parallel hierachies of
classes(no, I did not design this part and I graciously inherited as a
part of legacy code) with one hierachy of classes containing an array
of other appropriate classes. To make this a little clearer,

A<----B<----C<-----D and A is the pure abstract base class.

Now we have

E<----F<----G<----H and F,G,H have arrays of objects of kinds B,C and
D and E is of course the abstract base class.

Now, F,G,H return the arrays they contain to another function that
performs some calculation on it. So, they have to be of the kind A to
be generic and that is where the problem arises.

Here is my take on it: The parallel hierachy idea is not so great coz:
a) We are breaking the encapsulation principle. From what little
domain knowledge I have of the application, B,C and D have too much
coupling between them to be seperate classes.
b) There is some fault in the relationships between the huge number
classes I have and I have to figure that out.
c)To make the classes more cohesive, we have to bring in B,C and D as
data members of F,G and H(which can be done). This probably means that
B,C, and D were not probably that unique to be classes in the fist
place.

Am I talking sense or am I advertersing my ignorance? I find it a
little amusing that in IT, the fault of design is always with the
other guy. I try to manage my ego and not to do that. In this case, it
appears to be the case.

And I believe in the concepts of object orientation as "guidelines "
and not gospel and so will not hesistate to throw it out of the window
if there are tangible benefits. In this case though, it appears as if
the "guidelines " deserve more respect.

What say people?

Your responses will be gretly appreciated.

Cheers,
justanotherguy



al***@start.no (Alf P. Steinbach) wrote in message news:<41******* **********@news .individual.net >...
* Andrew Koenig:

In general, a container of derived objects cannot substitute for a
container of base objects, because what happens if you try to put a base
object into the container?


Is there any way in C++ to create a smartpointer that acts like a Java
reference?

Assuming there isn't (which is what I believe), is there any way the
language could be, er, "improved", so that that would be possible?

Jul 22 '05 #9
Thanks guys for your views. There were some very interesting and
innovative ways to work around the problem in the replies.Sorry for
getting back late because I had a bout of asthma and c++ was far from
my mind for the past few days.

Anyways, I did some soul searching about the design of the application
and the one point that came to my mind was what one friend of mine
used to say: "If it is too hard then maybe that is not the way it
should be". The problem was that there were two parallel hierachies of
classes(no, I did not design this part and I graciously inherited as a
part of legacy code) with one hierachy of classes containing an array
of other appropriate classes. To make this a little clearer,

A<----B<----C<-----D and A is the pure abstract base class.

Now we have

E<----F<----G<----H and F,G,H have arrays of objects of kinds B,C and
D and E is of course the abstract base class.

Now, F,G,H return the arrays they contain to another function that
performs some calculation on it. So, they have to be of the kind A to
be generic and that is where the problem arises.

Here is my take on it: The parallel hierachy idea is not so great coz:
a) We are breaking the encapsulation principle. From what little
domain knowledge I have of the application, B,C and D have too much
coupling between them to be seperate classes.
b) There is some fault in the relationships between the huge number
classes I have and I have to figure that out.
c)To make the classes more cohesive, we have to bring in B,C and D as
data members of F,G and H(which can be done). This probably means that
B,C, and D were not probably that unique to be classes in the fist
place.

Am I talking sense or am I advertersing my ignorance? I find it a
little amusing that in IT, the fault of design is always with the
other guy. I try to manage my ego and not to do that. In this case, it
appears to be the case.

And I believe in the concepts of object orientation as "guidelines "
and not gospel and so will not hesistate to throw it out of the window
if there are tangible benefits. In this case though, it appears as if
the "guidelines " deserve more respect.

What say people?

Your responses will be gretly appreciated.

Cheers,
justanotherguy



al***@start.no (Alf P. Steinbach) wrote in message news:<41******* **********@news .individual.net >...
* Andrew Koenig:

In general, a container of derived objects cannot substitute for a
container of base objects, because what happens if you try to put a base
object into the container?


Is there any way in C++ to create a smartpointer that acts like a Java
reference?

Assuming there isn't (which is what I believe), is there any way the
language could be, er, "improved", so that that would be possible?

Jul 22 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
4994
by: Banaticus Bart | last post by:
I wrote an abstract base class from which I've derived a few other classes. I'd like to create a base class array where each element is an instance of a derived object. I can create a base class pointer which points to an instance of a derived class, but when I pass that base class pointer into a function, it can't access the derived object's public functions. Although, the base class pointer does call the appropriate virtual function...
6
1615
by: Gernot Frisch | last post by:
I want to have a class that provides 2 methods with the same name (do1, do2) that cann be called from a function (Fkt) but Fkt does not know/care about it's type. class base { public: virtual void Do(base& b)=0; };
1
8349
by: Mark McDonald | last post by:
This question kind of follows on from Mike Spass’ posting 10/11/2004; I don’t understand why you can’t declare an implicit operator to convert a base class to a derived class. The text books say “neither the source nor the target types of a conversion can be a base type of the other, since a conversion would then already exist”. But this is not really true, whilst automatic (implicit) conversions do occur from the derived...
9
1800
by: Larry Woods | last post by:
I have a method in my base class that I want ALL derived classes to use. But, I find that I can create a "Shadow" method in my derived class that "overrides" the method in my base class. Can't figure out what attribute to put on the base class method to prevent this. TIA, Larry Woods
6
1774
by: MSDNAndi | last post by:
Hi, I have a baseclass (non-static) with some static and some non-static methods/fields/properties. In the baseclass in one of the static methods I need to do something like " somelogic .... CallToStaticMethod();
4
5244
by: Jeff | last post by:
The derived class below passes a reference to an object in its own class to its base calss constructor. The code compiles and will run successfully as long as the base class constructor does not attempt to access the object -- since m_object is not actually created and initizialized until after the base constructor has been called. Any thoughts on the practice below? class Base { public:
1
3966
by: autumn | last post by:
Hi everybody, I'm having problem passing pointer to member object as template argument, seems VC 2005 does not allow 'pointer to base member' to 'pointer to derived member' conversion in template arguments, is this VC specific or a standard c++ behavior? the code looks like this: class Base { public: int member; };
5
1821
by: Bushido Hacks | last post by:
I think this message got lost the first time I sent it, so I'm reposting it. I need a little help with Destructors. Suppose I created a multidimmensional array in a Base class that was also accessable in a Derived class, would I need to delete the array in the Derived class if I declared my destructors as virtual? class Base { public:
12
2718
by: subramanian100in | last post by:
Suppose class Base { public: virtual ~Test() { ... } // ... }; class Derived : public Base
0
8697
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9289
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9158
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9060
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9001
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7921
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
5939
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4454
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3151
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.