473,289 Members | 1,963 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,289 software developers and data experts.

Inheritance implementation just feels wrong, I need reasons though...

I tried for an hour to find some reference to concrete information on
why this particular inheritance implementation is a bad idea, but
couldn't. So I'm sorry if this has been answered before. Here's the
scenario:

We have a base class with all virtual functions. We'll call this the
Animal class. We then make two classes Fish and Bird that both inherit
from Animal. In the program, we have a single array of Animal pointers
that will house all of the Fish and Bird objects . For the most part,
they share functions (Eat, Breathe, etc.), so you would be able to just
call AnimalArray[i]->Eat() and it is handled polymorphically. Here is
my problem, let's say that you want to add a RuffleFeathers function to
the Bird class. Now in order to still call
AnimalArray[i]->RuffleFeathers(), I would have to add that function
definition to the Animal class, even though not all animals will have
feathers. So I just put a vitual function declaration and a stub with
a return statement in the Animal class, so if I call
AnimalArray[i]->RuffleFeathers() on a Fish object, it will just execute
the stub defined in Animal. To me, it just feels wrong to do it that
way.

Here's what the code would look like:

class Animal {

virtual void Eat() {return;}
virtual void RuffleFeathers() {return;}
};
class Bird : public Animal {

void Eat() {printf("Eat a mouse.");}
void RuffleFeathers {printf("Feathers ruffled.")};
};
class Fish : public Animal {

void Eat() {printf("Eat some kelp.");}
};
int main()
{
Animal* animalArray = new Animal[100];
animalArray[0] = new Fish();
animalArray[1] = new Bird();

animalArray[0]->Eat();
}

Now take this small example and extend it to 10 classes that inherit
from Animal with about 6 or so functions, like RuffleFeathers, that
have nothing to do with any of the other inherited classes. The thing
is that the implementation works, and you don't have to do a type check
or cast on each element in the single array before calling a function.
Nor do you have to keep multiple arrays of each type. But it just
seems wrong to change the base class to accomidate one of the children.
I have been under the impression that base classes should know nothing
of their children, and the sole purpose of inheritance was to extend
base classes. I just have no solid reason why this is a bad
implementation (if it even is a bad implementation). Any thoughts
would be great.

Aug 24 '06 #1
18 2295
bs****@gmail.com wrote:
We have a base class with all virtual functions. We'll call this the
Animal class. We then make two classes Fish and Bird that both inherit
from Animal. In the program, we have a single array of Animal pointers
that will house all of the Fish and Bird objects . For the most part,
they share functions (Eat, Breathe, etc.), so you would be able to just
call AnimalArray[i]->Eat() and it is handled polymorphically. Here is
my problem, let's say that you want to add a RuffleFeathers function to
the Bird class. Now in order to still call
AnimalArray[i]->RuffleFeathers(), I would have to add that function
The question can be: why you may want to do that? That is: did you really
want a container that can be described as "Animals that can ruffle
feathers"? If not, execute this code does not make sense, IMHO.

Maybe you need a more generic concept and function name, in response to
which the birds call RuffleFeathers and other animal do other things (or
nothing).

--
Salu2
Aug 24 '06 #2
zmc

bs****@gmail.com wrote:
We have a base class with all virtual functions. We'll call this the
Animal class. We then make two classes Fish and Bird that both inherit
from Animal. In the program, we have a single array of Animal pointers
that will house all of the Fish and Bird objects . For the most part,
they share functions (Eat, Breathe, etc.), so you would be able to just
call AnimalArray[i]->Eat() and it is handled polymorphically. Here is
my problem, let's say that you want to add a RuffleFeathers function to
the Bird class. Now in order to still call
AnimalArray[i]->RuffleFeathers(), I would have to add that function
definition to the Animal class, even though not all animals will have
feathers. So I just put a vitual function declaration and a stub with
a return statement in the Animal class, so if I call
AnimalArray[i]->RuffleFeathers() on a Fish object, it will just execute
the stub defined in Animal. To me, it just feels wrong to do it that
way.
I would say this is a very common issue to come up in any
class-oriented language. I don't think Animal should have a
RuffleFeathers method because Animal is an "interface" and should only
have methods shared/common with all derived classes, like you said. You
could add an extra enum data member (with a corresponding virtual
getType() maybe) for the type and do a type-check + downcast to call
the method that is only in the Bird class. Another solution would be to
generalize the additional functionality you want in derived classes
with a DoExtraAction( const char* action ) = 0; in the base class. Then
you would end up doing something like
a->DoExtraAction("RuffleFeathers"); where the bird class handled that
argument in a meaningful way (of course it doesn't have to be char*,
that's just a dead simple example.) That way isn't really that much
better than adding the RuffleFeathers to the base because you still end
up with logically useless function calls. Another way would be to
decouple extra actions to another interface... There are many ways to
achieve similar results, and I don't think there is a "best way" to
tackle this problem, there's ups and downs to all of them. Personally I
would probably go with some simple type data in the derived classes
with a getType() in the base class and cast to the proper type when you
need to call specialized methods. It avoids polluting the interface
with methods that might have NOTHING to do with derived classes.
Something about calling RuffleFeathers() on an AfricanElephant object
just doesn't sound right, even if it's a virtual call to an empty
method ;)

Aug 25 '06 #3

bs****@gmail.com wrote:
I tried for an hour to find some reference to concrete information on
why this particular inheritance implementation is a bad idea, but
couldn't. So I'm sorry if this has been answered before. Here's the
scenario:

We have a base class with all virtual functions. We'll call this the
Animal class. We then make two classes Fish and Bird that both inherit
from Animal. In the program, we have a single array of Animal pointers
that will house all of the Fish and Bird objects . For the most part,
they share functions (Eat, Breathe, etc.), so you would be able to just
call AnimalArray[i]->Eat() and it is handled polymorphically. Here is
my problem, let's say that you want to add a RuffleFeathers function to
the Bird class. Now in order to still call
AnimalArray[i]->RuffleFeathers(), I would have to add that function
definition to the Animal class, even though not all animals will have
feathers. So I just put a vitual function declaration and a stub with
a return statement in the Animal class, so if I call
AnimalArray[i]->RuffleFeathers() on a Fish object, it will just execute
the stub defined in Animal. To me, it just feels wrong to do it that
way.

Here's what the code would look like:

class Animal {

virtual void Eat() {return;}
virtual void RuffleFeathers() {return;}
};
class Bird : public Animal {

void Eat() {printf("Eat a mouse.");}
void RuffleFeathers {printf("Feathers ruffled.")};
};
class Fish : public Animal {

void Eat() {printf("Eat some kelp.");}
};
int main()
{
Animal* animalArray = new Animal[100];
animalArray[0] = new Fish();
animalArray[1] = new Bird();

animalArray[0]->Eat();
}

Now take this small example and extend it to 10 classes that inherit
from Animal with about 6 or so functions, like RuffleFeathers, that
have nothing to do with any of the other inherited classes. The thing
is that the implementation works, and you don't have to do a type check
or cast on each element in the single array before calling a function.
Nor do you have to keep multiple arrays of each type. But it just
seems wrong to change the base class to accomidate one of the children.
I have been under the impression that base classes should know nothing
of their children, and the sole purpose of inheritance was to extend
base classes. I just have no solid reason why this is a bad
implementation (if it even is a bad implementation). Any thoughts
would be great.
Without the context, we cannot give you a global well defined solution
because there is not one. But on my experience polluting base class is
not wise. "Base classes should know nothing of their children" is good.
But "the sole purpose of inheritance was to extend base classes" is not
the case. There are many purposes for us to inherit. In your case, you
define the base class as an interface. Therefore you inherit to
implement the interface not to extend. So if you want to add something
not in the interface and not for implementation, you should double
check your design.

Maybe you don't need such an interface, the base class is just for code
reuse. So you'd better not use a base array. Or maybe you can change
Ruffle to other more general interface.

The worst way is to use dynamic_cast rather than pollute the interface.

Aug 25 '06 #4
bs****@gmail.com wrote:
I tried for an hour to find some reference to concrete information on
why this particular inheritance implementation is a bad idea, but
couldn't. So I'm sorry if this has been answered before. Here's the
scenario:

We have a base class with all virtual functions. We'll call this the
Animal class. We then make two classes Fish and Bird that both inherit
from Animal. In the program, we have a single array of Animal pointers
that will house all of the Fish and Bird objects . For the most part,
they share functions (Eat, Breathe, etc.), so you would be able to just
call AnimalArray[i]->Eat() and it is handled polymorphically. Here is
my problem, let's say that you want to add a RuffleFeathers function to
the Bird class. Now in order to still call
AnimalArray[i]->RuffleFeathers(), I would have to add that function
definition to the Animal class, even though not all animals will have
feathers. So I just put a vitual function declaration and a stub with
a return statement in the Animal class, so if I call
AnimalArray[i]->RuffleFeathers() on a Fish object, it will just execute
the stub defined in Animal. To me, it just feels wrong to do it that
way.
[snip]
Now take this small example and extend it to 10 classes that inherit
from Animal with about 6 or so functions, like RuffleFeathers, that
have nothing to do with any of the other inherited classes. The thing
is that the implementation works, and you don't have to do a type check
or cast on each element in the single array before calling a function.
Nor do you have to keep multiple arrays of each type. But it just
seems wrong to change the base class to accomidate one of the children.
I have been under the impression that base classes should know nothing
of their children, and the sole purpose of inheritance was to extend
base classes. I just have no solid reason why this is a bad
implementation (if it even is a bad implementation). Any thoughts
would be great.
I'm sure it does feel wrong and there is a good reason for that. The
problem that you're finding is that every time you want to extend the
sub-classes you have to re-work the super class and that's just wrong.

There are a number of solutions. Taking your example at face value you
have in effect a Zoo instance that holds all of the animals. You have
two choices as you walk around the zoo, you can try to RuffleFeathers
on every animal you encounter, but then every animal has to have a
method to deal with it. The other obvious alternative is to check first
if the animal has feathers. This is your other alternative with a
dynamic_cast.

Personally I would prefer the dynamic_cast on the basis that the
function that is trying to RuffleFeathers knows the class definition
this is associated with. It means the Animal superclass stays clean and
means that the coupling is only between the class that has
RuffleFeathers and the function that uses it.

There are other ways of doing it. One obvious way is to segregate the
zoo by animal type. You may have something like this:

std::map< key, std::list< Animal * zoo;

You need to give quite some thought to exactly what you use for the key
though. There are a number of options, but all have potential problems.
Your problem domain may have an obvious key to use though. Note that
you will still need a cast, but at least you will get less "misses".

Still more exotic is to split the zoo up completely. Have each class
manage a list of its own instances. This may waste memory as you are
now storing lots of lists. You can work out agregates on the fly and
write your own iterators to manage it. Again, whether this feels good
or not depends on the problem domain. At least you'll know that you can
do Bird::birds.begin() to Bird::birds.end() and just RuffleFeathers and
it removes the casts.

Going another level on you could define an interface Feathered which
provides the RuffleFeathers and then use multiple inheritance for the
actual Animal sub-classes. I would normally lean towards using
dynamic_cast with this, but any of the other ways of finding the
instances work too. This solution is particularly good if you find
yourself making abstract superclasses between Animal and your leaf
classes just to hang the method on and it is a clear win where
otherwise unrelated sibling classes need the same method.
K

Aug 25 '06 #5

<bs****@gmail.comwrote in message
news:11**********************@74g2000cwt.googlegro ups.com...
>I tried for an hour to find some reference to concrete information on
why this particular inheritance implementation is a bad idea, but
couldn't. So I'm sorry if this has been answered before. Here's the
scenario:

We have a base class with all virtual functions. We'll call this the
Animal class. We then make two classes Fish and Bird that both inherit
from Animal. In the program, we have a single array of Animal pointers
that will house all of the Fish and Bird objects . For the most part,
they share functions (Eat, Breathe, etc.), so you would be able to just
call AnimalArray[i]->Eat() and it is handled polymorphically. Here is
my problem, let's say that you want to add a RuffleFeathers function to
the Bird class. Now in order to still call
AnimalArray[i]->RuffleFeathers(), I would have to add that function
definition to the Animal class, even though not all animals will have
feathers. So I just put a vitual function declaration and a stub with
a return statement in the Animal class, so if I call
AnimalArray[i]->RuffleFeathers() on a Fish object, it will just execute
the stub defined in Animal. To me, it just feels wrong to do it that
way.
It feels wrong to me, too. I wouldn't do it that way.

What I'd ask myself is, under what conditions do I want to call
RuffleFeathers in the first place? That's where I'd make the distinction.

Suppose, for example, I wanted to call RuffleFeathers when the bird is
disturbed by a loud noise. But for other animals, I'd want a different
reaction.

The function I'd put in my base class, and override in my derived classes,
could be RespondToLoudNoise (or something more general, like RespondTo(
LoudNoise )). For the bird, this might call a function RuffleFeathers which
is defined for the first time in the Bird class.

This way, there's no casting to the sub-class, or checking if a given
instance is of a particular class. It hides the details from users of the
base class pointers, so that all you have to worry about when dealing with a
collection of Animals is what Animals do, not what any specific sub-class of
Animals might do.

Other functions you might add could have to do with feeding, sunset or dawn,
or simply some amount of time going by (so that a given animal might
randomly yawn or something, once in a while). Just be sure to separate the
event from the specific animals' responses, and you're fine.

-Howard

Aug 25 '06 #6
Howard wrote:
<bs****@gmail.comwrote in message
news:11**********************@74g2000cwt.googlegro ups.com...
I tried for an hour to find some reference to concrete information on
why this particular inheritance implementation is a bad idea, but
couldn't. So I'm sorry if this has been answered before. Here's the
scenario:

We have a base class with all virtual functions. We'll call this the
Animal class. We then make two classes Fish and Bird that both inherit
from Animal. In the program, we have a single array of Animal pointers
that will house all of the Fish and Bird objects . For the most part,
they share functions (Eat, Breathe, etc.), so you would be able to just
call AnimalArray[i]->Eat() and it is handled polymorphically. Here is
my problem, let's say that you want to add a RuffleFeathers function to
the Bird class. Now in order to still call
AnimalArray[i]->RuffleFeathers(), I would have to add that function
definition to the Animal class, even though not all animals will have
feathers. So I just put a vitual function declaration and a stub with
a return statement in the Animal class, so if I call
AnimalArray[i]->RuffleFeathers() on a Fish object, it will just execute
the stub defined in Animal. To me, it just feels wrong to do it that
way.

It feels wrong to me, too. I wouldn't do it that way.

What I'd ask myself is, under what conditions do I want to call
RuffleFeathers in the first place? That's where I'd make the distinction.

Suppose, for example, I wanted to call RuffleFeathers when the bird is
disturbed by a loud noise. But for other animals, I'd want a different
reaction.

The function I'd put in my base class, and override in my derived classes,
could be RespondToLoudNoise (or something more general, like RespondTo(
LoudNoise )). For the bird, this might call a function RuffleFeathers which
is defined for the first time in the Bird class.

This way, there's no casting to the sub-class, or checking if a given
instance is of a particular class. It hides the details from users of the
base class pointers, so that all you have to worry about when dealing with a
collection of Animals is what Animals do, not what any specific sub-class of
Animals might do.

Other functions you might add could have to do with feeding, sunset or dawn,
or simply some amount of time going by (so that a given animal might
randomly yawn or something, once in a while). Just be sure to separate the
event from the specific animals' responses, and you're fine.

-Howard
Well, I'm glad that other people feel this is wrong, too. A little
more information:

The array of base class objects is surrounded by a container class.
This container class receives function calls from the rest of the
application, and passes those calls to the apropriate object. So it
would be something like:

Zoo::SetNumberOfFeedings(string animalName, int numberFeedings)
{
for(int i = 0; i < 100; i++) {
if(animalArray[i]->GetName() == animalName)
animalArray[i]->SetNumberOfFeedings(numberFeedings);
}
}

That code is definately much more simple than figuring out the type of
each animal, then casting the array item to make a call. Also,
Zoo::SetNumberOfFeedings probably won't be called with the name of an
object that doesn't support the SetNumberOfFeedings function. However,
more than one child class (but not all) may support the function, so I
can't just blindly assume a type, I still ned to check type and cast.

Other than the "not polluting the base class" reason, is there any
performance, memory usage, maintainability or some other quantifyable
reason why this is wrong? Or does it really boil down to a preference?
Thanks for all the responses.

Aug 25 '06 #7

<bs****@gmail.comwrote in message
news:11**********************@b28g2000cwb.googlegr oups.com...
Howard wrote:
><bs****@gmail.comwrote in message
news:11**********************@74g2000cwt.googlegr oups.com...
>>
Suppose, for example, I wanted to call RuffleFeathers when the bird is
disturbed by a loud noise. But for other animals, I'd want a different
reaction.

The function I'd put in my base class, and override in my derived
classes,
could be RespondToLoudNoise (or something more general, like RespondTo(
LoudNoise )). For the bird, this might call a function RuffleFeathers
which
is defined for the first time in the Bird class.

This way, there's no casting to the sub-class, or checking if a given
instance is of a particular class. It hides the details from users of
the
base class pointers, so that all you have to worry about when dealing
with a
collection of Animals is what Animals do, not what any specific sub-class
of
Animals might do.

Other functions you might add could have to do with feeding, sunset or
dawn,
or simply some amount of time going by (so that a given animal might
randomly yawn or something, once in a while). Just be sure to separate
the
event from the specific animals' responses, and you're fine.

-Howard

Well, I'm glad that other people feel this is wrong, too. A little
more information:

The array of base class objects is surrounded by a container class.
This container class receives function calls from the rest of the
application, and passes those calls to the apropriate object. So it
would be something like:

Zoo::SetNumberOfFeedings(string animalName, int numberFeedings)
{
for(int i = 0; i < 100; i++) {
if(animalArray[i]->GetName() == animalName)
animalArray[i]->SetNumberOfFeedings(numberFeedings);
}
}

That code is definately much more simple than figuring out the type of
each animal, then casting the array item to make a call. Also,
Zoo::SetNumberOfFeedings probably won't be called with the name of an
object that doesn't support the SetNumberOfFeedings function. However,
more than one child class (but not all) may support the function, so I
can't just blindly assume a type, I still ned to check type and cast.
Notice this comment: "Zoo::SetNumberOfFeedings probably won't be called
with the name of an object that doesn't support the SetNumberOfFeedings
function." The point where you make the decision whether to call or not
call SetNumberOfFeedings for an animal with a given name is the point where
you could put a virtual function.

It looks like you're comparing animal names (like "Lion", I assume) to see
if they meet a criteria. At that point, you could simply cast to the known
type. That's ok, but you might consider a different tack.

Suppose you want to schedule feeding for all the Lions. Suppose also that
you want to keep using their names as an indicator of their type. (Not my
choice for the design, but let's keep it for now.)

You could have a function which traverses the list as in your example, but
instead of calling SetNumberOfFeedings for each one, it simply builds a new
list of all the Lions, storing pointers to Lion objects instead of Animal
objects. Then, after building the list of Lions, you could loop through
that list, and calling the SetNumberOfFeedings for the Lions. Then you
could just dispose of that list of Lions. The do the same for Birds (or for
whatever species you wish to call that functon).

---

Another alternative is to create a sub-class of Animal for which
SetNumberOfFeedings is valid, and descend appropriate animal classes from
that. Such a design can become pretty tangled up in multiple inheritance,
however, if there are various criteria by which the animals might be
categorized.

---

A third idea is to not store all the animals in one huge list, but instead
to store them in objects which hold a list of the appropriate animal type.
So then you'd have a Lion list object, a Bird list object, a Monkey list
object, etc. To feed all the animals, you call on the sub-object for each
animal type you've created, such as Zoo.Lions.Feed(). (The Lions list would
hold pointers to Lions, not pointers to Animals. If you need to extract a
particular Lion for use in a generic "all animals do this" kind of function,
you can always assign the pointer to an Animal* pointer, since a Lion "is
an" animal.)

You could also keep a master list of Animals using this idea, but whenever
you did something like Add or Remove a lion from the Lions list object (for
instance), you'd want to do the same for the master Zoo list as well.

---

One other note: why use a string for the type? I'd think an integer or enum
would be more appropriate. Or, some kind of hierarchical structure, such as
something which specifies the order, family, genus, and species (or however
that stuff is formally organized). And each of those categories could use
enumerations.

An extension of that idea might be to store that kind of scientific
designation stuff in a lookup table, and use the index into that table as an
ID field in the Animal data structure. That's how it's done in database
programming, and it works well, allowing you to add types more easily.

I think that strings would best be used just for outputting, via a couple
functions, such as getScientificName() and getCommonName(). Due to the fact
that comparing strings is relatively slow, and the possibility of spelling
errors, I think that strings are not that commonly used as identifiers.

-Howard


Aug 25 '06 #8

Kirit Sælensminde wrote:
There are a number of solutions. Taking your example at face value you
have in effect a Zoo instance that holds all of the animals. You have
two choices as you walk around the zoo, you can try to RuffleFeathers
on every animal you encounter, but then every animal has to have a
method to deal with it. The other obvious alternative is to check first
if the animal has feathers. This is your other alternative with a
dynamic_cast.

Personally I would prefer the dynamic_cast on the basis that the
function that is trying to RuffleFeathers knows the class definition
this is associated with. It means the Animal superclass stays clean and
means that the coupling is only between the class that has
RuffleFeathers and the function that uses it.
A better option would be to establish why a bird might ruffle its
feathers. Do all animals share this? For instance, for eat you could
have originally had "chew". Obviously a bird doesn't chew as it has no
teeth, neither do many wales and fish just swallow things whole much of
the time.

So, you might have something like

class Animal
{
public:
virtual void wiggle() = 0;
};

class Bird
{
public:
virtual void ruffle() {}
void wiggle() { ruffle(); }
};

and there you go.

I see dynamic_casts quite a bit in some books like the object mentor
agile book. It always makes me cringe. Use of dynamic_cast indicates
a violation of LSP. In my book its a smell.

Aug 25 '06 #9

bs****@gmail.com wrote:
Other than the "not polluting the base class" reason, is there any
performance, memory usage, maintainability or some other quantifyable
reason why this is wrong? Or does it really boil down to a preference?
The "not polluting the base class" reason is a good reason. There are
concequences to violating this principle in code reuse,
understandability, and changeability. Polluting a base class makes
your code rigid and difficult to change.

Aug 25 '06 #10

Howard wrote:
Notice this comment: "Zoo::SetNumberOfFeedings probably won't be called
with the name of an object that doesn't support the SetNumberOfFeedings
function." The point where you make the decision whether to call or not
call SetNumberOfFeedings for an animal with a given name is the point where
you could put a virtual function.

It looks like you're comparing animal names (like "Lion", I assume) to see
if they meet a criteria. At that point, you could simply cast to the known
type. That's ok, but you might consider a different tack.

Suppose you want to schedule feeding for all the Lions. Suppose also that
you want to keep using their names as an indicator of their type. (Not my
choice for the design, but let's keep it for now.)

You could have a function which traverses the list as in your example, but
instead of calling SetNumberOfFeedings for each one, it simply builds a new
list of all the Lions, storing pointers to Lion objects instead of Animal
objects. Then, after building the list of Lions, you could loop through
that list, and calling the SetNumberOfFeedings for the Lions. Then you
could just dispose of that list of Lions. The do the same for Birds (or for
whatever species you wish to call that functon).

---

Another alternative is to create a sub-class of Animal for which
SetNumberOfFeedings is valid, and descend appropriate animal classes from
that. Such a design can become pretty tangled up in multiple inheritance,
however, if there are various criteria by which the animals might be
categorized.

---

A third idea is to not store all the animals in one huge list, but instead
to store them in objects which hold a list of the appropriate animal type.
So then you'd have a Lion list object, a Bird list object, a Monkey list
object, etc. To feed all the animals, you call on the sub-object for each
animal type you've created, such as Zoo.Lions.Feed(). (The Lions list would
hold pointers to Lions, not pointers to Animals. If you need to extract a
particular Lion for use in a generic "all animals do this" kind of function,
you can always assign the pointer to an Animal* pointer, since a Lion "is
an" animal.)

You could also keep a master list of Animals using this idea, but whenever
you did something like Add or Remove a lion from the Lions list object (for
instance), you'd want to do the same for the master Zoo list as well.

---

One other note: why use a string for the type? I'd think an integer or enum
would be more appropriate. Or, some kind of hierarchical structure, such as
something which specifies the order, family, genus, and species (or however
that stuff is formally organized). And each of those categories could use
enumerations.

An extension of that idea might be to store that kind of scientific
designation stuff in a lookup table, and use the index into that table as an
ID field in the Animal data structure. That's how it's done in database
programming, and it works well, allowing you to add types more easily.

I think that strings would best be used just for outputting, via a couple
functions, such as getScientificName() and getCommonName(). Due to the fact
that comparing strings is relatively slow, and the possibility of spelling
errors, I think that strings are not that commonly used as identifiers.

-Howard
Looks like it is time to abandon the Zoo analogy. We have a system
where the user can set properties either via a networked application,
loading an ASCII configuration file, or via the UI. In order for these
three separate classes to access the underlying objects that they are
going to configure, they call a function in the object container class
with the ID of the object whose property they wish to change, along
with the value they wish to change
(gContainer::SetNumberOfBoards("VT1", 3) where VT1 is the ID of the
object we want to change). For alot of the properties, all the objects
in that base class array have an implemented function. However, each
subclass has some functions that are completely unique to that
subclass, so they can not be grouped. There are two reasons that we
are using a base class:

1) Code reuse for actions similar to all children.
2) So that we can have a single array that holds all of the objects in
the container.

I just hate the fact that every time I want to add a new object to that
list, and have to inherit from the base class, I need to go back into
the base class (and the container class) and add functions to make my
new class work.

This is a design decision that the boss has made, I'm not comfortable
with it, but have no quantifyable reason as to why it is bad (extra
processing costs for excessive virtual function usage maybe?) He
believes that the code is more "maintainable" and "bullet proof" using
this method. I think it just makes everything ugly. I can only think
of two alternatives:

1) the container maintains a list of each subclass, not a single list
of the base class.
2) Find out the type of each object in the single list of baseclass
objects, and do a cast to the apropriate type in order to call the
specialized function.

I just need some reason to justify either of those two options over
what has been chosen. Or you all can tell me that this is no big deal,
cash my paycheck and do what the boss wants. Again, thank you for the
replies.

Aug 25 '06 #11
One more note:

Basically the boss likes the polymorphic behavior of something like Eat
while still being able to call RuffleFeathers without having to do any
type checking or casting.

Aug 25 '06 #12

<bs****@gmail.comwrote in message
news:11**********************@p79g2000cwp.googlegr oups.com...
>
>
Looks like it is time to abandon the Zoo analogy. We have a system
where the user can set properties either via a networked application,
loading an ASCII configuration file, or via the UI. In order for these
three separate classes to access the underlying objects that they are
going to configure, they call a function in the object container class
with the ID of the object whose property they wish to change, along
with the value they wish to change
(gContainer::SetNumberOfBoards("VT1", 3) where VT1 is the ID of the
object we want to change). For alot of the properties, all the objects
in that base class array have an implemented function. However, each
subclass has some functions that are completely unique to that
subclass, so they can not be grouped. There are two reasons that we
are using a base class:

1) Code reuse for actions similar to all children.
2) So that we can have a single array that holds all of the objects in
the container.

I just hate the fact that every time I want to add a new object to that
list, and have to inherit from the base class, I need to go back into
the base class (and the container class) and add functions to make my
new class work.

This is a design decision that the boss has made, I'm not comfortable
with it, but have no quantifyable reason as to why it is bad (extra
processing costs for excessive virtual function usage maybe?) He
believes that the code is more "maintainable" and "bullet proof" using
this method. I think it just makes everything ugly. I can only think
of two alternatives:

1) the container maintains a list of each subclass, not a single list
of the base class.
2) Find out the type of each object in the single list of baseclass
objects, and do a cast to the apropriate type in order to call the
specialized function.

I just need some reason to justify either of those two options over
what has been chosen. Or you all can tell me that this is no big deal,
cash my paycheck and do what the boss wants. Again, thank you for the
replies.
"Cash your paycheck, and do what the boss wants." :-)

Seriously, you'd need to look at the specifics of what functions are added,
and what they do, and decide for yourself the appropriate solution (since
only you can see the code at this point).

Even though you've changed from "animals" to some other classification of
objects, the idea is still the same. At the point where you're making the
call to SetNumberOfBoards, passing it "VT1", you know that you're dealing
with VT1-type objects.

At that point, you could dynamically build a list of objects whose ID is
"VT1", and then loop over the resulting list, using a pointer to the
appropriate sub-class and calling the desired function. Or, you could
simply cast to the known type.

Then, for other objects that you'd be calling the SetNumberOfBoards function
for, do the same thing.

(There might also be some kind of template solution that would work, but I'm
not familair enough with creating templates to offer a good suggestion.)

Or, as you say, separate lists would work well also. I like that idea,
provided that membership in a given lists means not being a member of
another list. If an object could be a member of multiple lists, then you
either need to maintain a master list which "owns" the actual objects, or
else use some kind of reference-counted pointer (which isn't a bad idea
itself, by the way).

Casting is also a viable option, but how do you know what to cast to? You
either need multiple loops (such as I mentioned above), or some kind of
if-else-if-else or switch statement to cast to the correct sub-type.

Finally, if the number of these functions is fairly small (and will remain
so), then "polluting" the base class isn't really all that bad. I am
working on a project where we do that, but in my case there's just a couple
such functions and a couple sub-classes to deal with, and that likely won't
change. We simply document this in the base class header file: "This
function does nothing unless overridden by a sub-class. Check the specific
sub-class of interest for information regarding its behavior."

Hope this helps...
-Howard
Aug 25 '06 #13

Howard wrote:
"Cash your paycheck, and do what the boss wants." :-)

Seriously, you'd need to look at the specifics of what functions are added,
and what they do, and decide for yourself the appropriate solution (since
only you can see the code at this point).

Even though you've changed from "animals" to some other classification of
objects, the idea is still the same. At the point where you're making the
call to SetNumberOfBoards, passing it "VT1", you know that you're dealing
with VT1-type objects.
"VT1" is not a type, it is a unique ID, and the ID tells me nothing
about what type the object is.
At that point, you could dynamically build a list of objects whose ID is
"VT1", and then loop over the resulting list, using a pointer to the
appropriate sub-class and calling the desired function. Or, you could
simply cast to the known type.

Then, for other objects that you'd be calling the SetNumberOfBoards function
for, do the same thing.

(There might also be some kind of template solution that would work, but I'm
not familair enough with creating templates to offer a good suggestion.)

Or, as you say, separate lists would work well also. I like that idea,
provided that membership in a given lists means not being a member of
another list. If an object could be a member of multiple lists, then you
either need to maintain a master list which "owns" the actual objects, or
else use some kind of reference-counted pointer (which isn't a bad idea
itself, by the way).

Casting is also a viable option, but how do you know what to cast to? You
either need multiple loops (such as I mentioned above), or some kind of
if-else-if-else or switch statement to cast to the correct sub-type.
Objects will never be able to belong to multiple lists. Also, the
specialized functions only belong to a single subclass. You will never
have two subclasses using one of those "extra" base class functions.
So if SetNumberOfBoards is not supported by SubClass1, but is supported
by SubClass2, I can safely assume that
gObjects::SetNumberOfBoards("foo", 4) will be working on an object of
type SubClass2 with ID = "foo".
Finally, if the number of these functions is fairly small (and will remain
so), then "polluting" the base class isn't really all that bad. I am
working on a project where we do that, but in my case there's just a couple
such functions and a couple sub-classes to deal with, and that likely won't
change. We simply document this in the base class header file: "This
function does nothing unless overridden by a sub-class. Check the specific
sub-class of interest for information regarding its behavior."

Hope this helps...
-Howard
If it were only a few functions, I wouldn't care as much. Right now it
isn't totally unmanageable, but I see it getting out of control in the
future. We are redesigning a system where every object, inherited from
a base class and did drastically different things. Imagine the
scenario I have been describing for about 50 classes some of them with
3 or 4 levels of inheritance. And the boss loved that design. He
loved how if you called a function on one of the lowest classes on the
tree, it would filter up the inheritance tree until someone handled it,
and if it got to the base class, it threw an error. And the
application had one huge array with all the objects in the application.
A completely horrible design, where you never really knew what type
anything was. This is why this small decision in the new design
bothers me.

What could I bring to the table to convince him that these "extra"
functions are the start of something bad. I need some performance or
memory management or some quantifyable way of convincing him that this
is wrong and it needs to be changed now, before it goes too far again.

Aug 25 '06 #14

Noah Roberts wrote:
Kirit Sælensminde wrote:
There are a number of solutions. Taking your example at face value you
have in effect a Zoo instance that holds all of the animals. You have
two choices as you walk around the zoo, you can try to RuffleFeathers
on every animal you encounter, but then every animal has to have a
method to deal with it. The other obvious alternative is to check first
if the animal has feathers. This is your other alternative with a
dynamic_cast.

Personally I would prefer the dynamic_cast on the basis that the
function that is trying to RuffleFeathers knows the class definition
this is associated with. It means the Animal superclass stays clean and
means that the coupling is only between the class that has
RuffleFeathers and the function that uses it.

A better option would be to establish why a bird might ruffle its
feathers. Do all animals share this? For instance, for eat you could
have originally had "chew". Obviously a bird doesn't chew as it has no
teeth, neither do many wales and fish just swallow things whole much of
the time.
I think you're getting the actors confused here. The OP was talking
about some external client that wished to use a RuffleFeathers member
on whichever animals support it. They were _not_ talking about some
animals ruffling their own feathers if they could.
>
So, you might have something like

class Animal
{
public:
virtual void wiggle() = 0;
};

class Bird
{
public:
virtual void ruffle() {}
void wiggle() { ruffle(); }
};

and there you go.
What's wiggle? Playing semantic games where you change method names
into ever more abstract names is not generally a good idea. For some
problems it may work out, but in general you are simply swapping the
addition of ruffle() in Animal for wiggle(). For some future extension
of the Animal hierarchy you may well end up adding members to Animal
and for no good reason other than to avoid a cast.

The point about finding a more general substitution is a good one, but
many crimes are done in trying to over complicate method names and
argument lists where a simpler design keeps things more relevant at
every level of the class hierarchy.
>
I see dynamic_casts quite a bit in some books like the object mentor
agile book. It always makes me cringe. Use of dynamic_cast indicates
a violation of LSP. In my book its a smell.
That depends. If the dynamic_cast is there as a substitute for code
reflection I think it is often Ok (not always, but often). If the
dynamic_cast is there due to poor understanding of C++, i.e. when the
language provides a better alternative, then it is wrong.

For example, the zoo loop in Javascript I would just have something
like this:

for ( each a in Zoo )
if ( Zoo[ a ].RuffleFeathers )
Zoo[ a ].RuffleFeathers();

This is a common sort of idiom - iterate over a collection and perform
a funcion if a condition is met. In C++ you probably wouldn't think
twice about:

for ( list< Animal * >::iterator it( Zoo.begin() ); it != Zoo.end();
++it )
if ( (*it).isBird )
(*it)->RuffleFeathers();

But now we're polluting the Animal class with extra members are that
are irrelevant to it. Here I think the dynamic_cast is a _much better_
solution.

for ( list< Animal * >::iterator it( Zoo.begin() ); it != Zoo.end();
++it )
if ( dynamic_cast< Bird * >( *it ) )
dynamic_cast< Bird * >( *it )->RuffleFeathers();

This is the nearest C++ analog to the Javascript case and involves no
pollution of Animal. This dynamic_cast is fine.

LSP is Ok here too because you are still preserving the
substitutability of Animal sub-classes to the function using it. No
matter what sorts of sub-classes are introduced and no matter what
sorts of capabilities the dynamic_cast will always work and we'll never
have to edit the Animal class definition.

The only time that you break LSP is if you introduce some other
class/hierarchy (i.e. Archeoptrix) that also has feathers. This is the
situation where I suggest an interface approach with multiple
inheritance instead.
K

Aug 26 '06 #15
In article <11*********************@75g2000cwc.googlegroups.c om>,
bs****@gmail.com says...

[ ... ]
If it were only a few functions, I wouldn't care as much. Right now it
isn't totally unmanageable, but I see it getting out of control in the
future. We are redesigning a system where every object, inherited from
a base class and did drastically different things. Imagine the
scenario I have been describing for about 50 classes some of them with
3 or 4 levels of inheritance. And the boss loved that design. He
loved how if you called a function on one of the lowest classes on the
tree, it would filter up the inheritance tree until someone handled it,
and if it got to the base class, it threw an error. And the
application had one huge array with all the objects in the application.
A completely horrible design, where you never really knew what type
anything was. This is why this small decision in the new design
bothers me.
Except for the "one huge array" part, this really isn't such a horrible
design -- it's just a C++ design. This is pretty much how the Smalltalk
class hierarchy (for one example) is designed, and it works pretty well
under the right circumstances.

This sort of design doesn't work well at all in C++ though. One of the
major strengths of C++ is static type checking. In C++ the notion of
type is largely a set of operations that can be carried out by/on a
particular object. The static type checking means that the compiler
enforces (at compile time) the fact that even attempting to carry out
some operations on some types is an error. The compiler automatically
carries out these checks, drastically improving the chances that a
design that's never going to work won't compile at all.

By contrast, this design shifts the burden from the compiler to the
programmers. It's up to the programmers to assure that every class has
every possible function implemented in a way that's suitable for that
class. If that function is meaningless for the class, the class still
has to implement graceful failure. Then it's up to the programmers to
assure that (for example) every function is written in a way that the
higher level code never depends on the function actually succeeding --
quite the contrary, knowing up-front that many functions may fail a
substantial percentage of the time.

That, in turn, means the rest of the code gets ugly in a hurry -- rather
than checking types and doing downcasting when necessary, nearly all of
your code ends up sprinkled with special cases dealing with (for one
example) the fact that you've changed what were fundamentally two cases
into three cases. Normally, the two cases are: 1) the function
succeeded, 2) the function failed -- something's wrong. You're adding 3)
the function failed -- but nothing's wrong.
What could I bring to the table to convince him that these "extra"
functions are the start of something bad. I need some performance or
memory management or some quantifyable way of convincing him that this
is wrong and it needs to be changed now, before it goes too far again.
If memory usage is a real concern, you might have a fairly quantifiable
argument: each function you add to the base class makes the base class'
vtable larger. In addition, it makes the vtable of every derived class
larger as well -- each derived class vtable is a superset of its base
class' vtable.

Realistically, that's the least of your problems though -- your real
problems are that 1) you've almost entirely subverted the compiler's
type-checking ability, 2) each class has to implement the union of all
the behaviors of all the classes, 3) you can't depend on functions to
succeed, and when they fail you can't depend on it to mean there's a
problem (except in the class design).

My final advice: if this is really how your boss likes designing things,
there are a lot of ther languages (e.g. Smalltalk) that fit this kind of
design much more closely. It just doesn't fit well with C++ at all. It
loses most of the benefits that C++ can provide. If you're going to do a
design that's basically dynamically typed, you'd be a lot better off
using a language that explicitly supports dynamic typing and provides
tools for doing it much more cleanly.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 26 '06 #16
In article <MP************************@news.sunsite.dk>,
jc*****@taeus.com says...

[ ... ]
Except for the "one huge array" part, this really isn't such a horrible
design -- it's just a C++ design.
Oops -- of course that should say: "it's just NOT a C++ design."

--
Later,
Jerry.

The universe is a figment of its own imagination.
Aug 26 '06 #17

Jerry Coffin wrote:
In article <MP************************@news.sunsite.dk>,
jc*****@taeus.com says...

[ ... ]
Except for the "one huge array" part, this really isn't such a horrible
design -- it's just a C++ design.

Oops -- of course that should say: "it's just NOT a C++ design."

--
Later,
Jerry.

The universe is a figment of its own imagination.
Changing languages is not an option.

I presented some of the ideas in this thread to one of the other
programmers (one who likes the current implementation) and he didn't
think there was enough here to convince him to change his mind. I
guess I'll just have to deal with it. Or read Design Patterns and see
if there is a better solution to this problem. Thanks for all the
comments.

Aug 28 '06 #18

Oh, too many replys to watch:) I just have some more comments.

1, Big base which contain many virtual functions can give you a large
vtable for each subclass. But only if you have many many subclasses,
you have to consider that.

2, dynamic_cast requires runtime check which will cost your time

3, Considering your project scale when make decision. How large it is?
How fast it may change. And the purpose of it. If you change the
project changes too frequently, such as add a new kind of animal per
day or and new function per day, you'd better use embed script if
change language is not possible or make your code more dynamic. If the
project is not so big and may not always change, a simple
implementation may be acceptable even though it is ugly. If your
purpose is to make a framework, flexiblity is your first consideration.
Or a efficient simple implementation may be good.

4, Persuading a programmer to change his/her opinion is too difficult
to do. We are always on our own world and don't want others to disturb
us:)

5, You may check the Visitor pattern. It can give you the ablity to add
different functions to different subclasses in a large container very
flexiblly with constration that it is hard to add new subclass. Of
course, you have to pay for its complexity
bs****@gmail.com wrote:
Jerry Coffin wrote:
In article <MP************************@news.sunsite.dk>,
jc*****@taeus.com says...

[ ... ]
Except for the "one huge array" part, this really isn't such a horrible
design -- it's just a C++ design.
Oops -- of course that should say: "it's just NOT a C++ design."

--
Later,
Jerry.

The universe is a figment of its own imagination.

Changing languages is not an option.

I presented some of the ideas in this thread to one of the other
programmers (one who likes the current implementation) and he didn't
think there was enough here to convince him to change his mind. I
guess I'll just have to deal with it. Or read Design Patterns and see
if there is a better solution to this problem. Thanks for all the
comments.
Aug 29 '06 #19

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

Similar topics

14
by: Steve Jorgensen | last post by:
Recently, I tried and did a poor job explaining an idea I've had for handling a particular case of implementation inheritance that would be easy and obvious in a fully OOP language, but is not at...
12
by: Steve Jorgensen | last post by:
The classing Visual Basic and VBA support for polymorphism, let's face it, is a bit on the weak side, and built-in support for inheritance is non-existent. This little essay is about some patterns...
22
by: Matthew Louden | last post by:
I want to know why C# doesnt support multiple inheritance? But why we can inherit multiple interfaces instead? I know this is the rule, but I dont understand why. Can anyone give me some concrete...
3
by: enchantingdb | last post by:
I have an exam tomorrow that covers the perceived advantages and disadvantages of object oriented programming, in particular polymorphism, inheritance and encapsulation. I know the advantages but...
1
by: vinoraja | last post by:
There are a number of reasons we don't implement Multiple Implementation Inheritance directly. (As you know, we support Multiple Interface Inheritance). However, I should point out that it's...
0
by: Terry Hancock | last post by:
I've been discussing PyProtocols with a a friend collaborating with me on a SF game project, about the benefits and design concept of "component architecture", and I'm a little confused by what...
47
by: Mark | last post by:
why doesn't .NET support multiple inheritance? I think it's so silly! Cheers, Mark
6
by: tshad | last post by:
I am playing with Inheritance and want to make sure I understand it. I have the following Classes: ******************************************* Public Class AuthHeader:Inherits SoapHeader Public...
3
by: Leo Seccia | last post by:
Hello everyone, I have a c# project with a sql server database. I have a number of lookup tables in my database which I successfully managed to import into my LINQ dataclasses. eg. Table:...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 7 Feb 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:30 (7.30PM). In this month's session, the creator of the excellent VBE...
0
by: Aftab Ahmad | last post by:
Hello Experts! I have written a code in MS Access for a cmd called "WhatsApp Message" to open WhatsApp using that very code but the problem is that it gives a popup message everytime I clicked on...
0
by: Aftab Ahmad | last post by:
So, I have written a code for a cmd called "Send WhatsApp Message" to open and send WhatsApp messaage. The code is given below. Dim IE As Object Set IE =...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: marcoviolo | last post by:
Dear all, I would like to implement on my worksheet an vlookup dynamic , that consider a change of pivot excel via win32com, from an external excel (without open it) and save the new file into a...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...

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.