most elegant solution - empty virtual funciton, rtti or static data member? | | |
Problem:
I have a vector full of two different derived class objects (class B
and class C) that are derived from the same base class A. I want to
loop through vector and invoke a member function in only objects of
class B and skip over the objects of class C. To complicate things,
I'm using the vector position (index) as an argument in the invoked
member function. It is possible to move the position into the object
by adding a data member, but that feels like duplicating data when I'm
trying to keep things streamlined. I also think that needing to use
the vector index pretty much kills sorting or other use of iterators
or separate vectors.
The possible solutions that I have thought of are:
1. Calling a common virtual function of each object through a base
class pointer, while leaving the virtual function for class C (the
objects to skip) empty. Cons - Empty member functions seem ugly.
2. Using run-time type identification (typeid() == typid()) and a
series of if () else statments to skip the objects of class C. Cons -
The ensuing if-else tree feels like a botched switch statement.
3. Creating a static data member in each class that holds an int that
corresponds to the class type. Then, using this value in a switch
statement to skip over the objects of class C. Cons - I like the
switch in this step as opposed to solution 2, but it feels wrong
duplicating type information.
Am I missing something obvious, or if I'm moving in the right
direction, which of the solutions is the most elegant? If you're
feeling especially generous I would love to be told why any of my
ideas suck and why the best idea is the best.
Thanks for any help,
-Mark | | | | re: most elegant solution - empty virtual funciton, rtti or static data member?
Mark Turney wrote:[color=blue]
> Problem:
> I have a vector full of two different derived class objects (class B
> and class C) that are derived from the same base class A. I want to
> loop through vector and invoke a member function in only objects of
> class B and skip over the objects of class C. To complicate things,
> I'm using the vector position (index) as an argument in the invoked
> member function. It is possible to move the position into the object
> by adding a data member, but that feels like duplicating data when I'm
> trying to keep things streamlined. I also think that needing to use
> the vector index pretty much kills sorting or other use of iterators
> or separate vectors.
>
> The possible solutions that I have thought of are:
> 1. Calling a common virtual function of each object through a base
> class pointer, while leaving the virtual function for class C (the
> objects to skip) empty. Cons - Empty member functions seem ugly.[/color]
Get over it. Your class A should have that function empty and not
pure. Class B will redefine it by overriding. Class C won't.
[color=blue]
> 2. Using run-time type identification (typeid() == typid()) and a
> series of if () else statments to skip the objects of class C. Cons -
> The ensuing if-else tree feels like a botched switch statement.[/color]
That's definitely true.
[color=blue]
> 3. Creating a static data member in each class that holds an int that
> corresponds to the class type. Then, using this value in a switch
> statement to skip over the objects of class C. Cons - I like the
> switch in this step as opposed to solution 2, but it feels wrong
> duplicating type information.[/color]
Not only that, but then what if you add class 'D' to the mix? Now
you have to remember to implement that nonsense in it as well.
[color=blue]
> Am I missing something obvious, or if I'm moving in the right
> direction, which of the solutions is the most elegant? If you're
> feeling especially generous I would love to be told why any of my
> ideas suck and why the best idea is the best.[/color]
Since you imply polymorphism when you store pointers to objects
of two different types in the same container, you should stick to
your convictions and use polymorphism wherever possible. Going
off and re-implementing RTTI by whatever means may be tempting,
but trust me, it's not a good idea.
Victor | | | | re: most elegant solution - empty virtual funciton, rtti or static data member?
Uzytkownik "Victor Bazarov" <v.Abazarov@comAcast.net> napisal w wiadomosci
news:RpHvc.912$ri.77972@dfw-read.news.verio.net...[color=blue]
> Mark Turney wrote:[color=green]
> > Problem:
> > I have a vector full of two different derived class objects (class B
> > and class C) that are derived from the same base class A. I want to
> > loop through vector and invoke a member function in only objects of
> > class B and skip over the objects of class C. To complicate things,
> > I'm using the vector position (index) as an argument in the invoked
> > member function. It is possible to move the position into the object
> > by adding a data member, but that feels like duplicating data when I'm
> > trying to keep things streamlined. I also think that needing to use
> > the vector index pretty much kills sorting or other use of iterators
> > or separate vectors.
> >
> > The possible solutions that I have thought of are:
> > 1. Calling a common virtual function of each object through a base
> > class pointer, while leaving the virtual function for class C (the
> > objects to skip) empty. Cons - Empty member functions seem ugly.[/color]
>
> Get over it. Your class A should have that function empty and not
> pure. Class B will redefine it by overriding. Class C won't.
>[color=green]
> > 2. Using run-time type identification (typeid() == typid()) and a
> > series of if () else statments to skip the objects of class C. Cons -
> > The ensuing if-else tree feels like a botched switch statement.[/color]
>
> That's definitely true.
>[color=green]
> > 3. Creating a static data member in each class that holds an int that
> > corresponds to the class type. Then, using this value in a switch
> > statement to skip over the objects of class C. Cons - I like the
> > switch in this step as opposed to solution 2, but it feels wrong
> > duplicating type information.[/color]
>
> Not only that, but then what if you add class 'D' to the mix? Now
> you have to remember to implement that nonsense in it as well.
>[color=green]
> > Am I missing something obvious, or if I'm moving in the right
> > direction, which of the solutions is the most elegant? If you're
> > feeling especially generous I would love to be told why any of my
> > ideas suck and why the best idea is the best.[/color]
>
> Since you imply polymorphism when you store pointers to objects
> of two different types in the same container, you should stick to
> your convictions and use polymorphism wherever possible. Going
> off and re-implementing RTTI by whatever means may be tempting,
> but trust me, it's not a good idea.
>[/color]
If your hierarchy has only 2 "types" of classes, ones that should be checked
and ones that should not, you could consider having 2 vectors that store
them separately. If possible, it's always better to use compile-time
facilities than runtime.
Best regards,
Marcin | | | | re: most elegant solution - empty virtual funciton, rtti or static data member?
"Mark Turney" <google@freelance3d.com> wrote in message
news:ec18a62c.0406030719.79c7890d@posting.google.c om...[color=blue]
> Problem:
> I have a vector full of two different derived class objects (class B
> and class C) that are derived from the same base class A. I want to
> loop through vector and invoke a member function in only objects of
> class B and skip over the objects of class C. To complicate things,
> I'm using the vector position (index) as an argument in the invoked
> member function. It is possible to move the position into the object
> by adding a data member, but that feels like duplicating data when I'm
> trying to keep things streamlined. I also think that needing to use
> the vector index pretty much kills sorting or other use of iterators
> or separate vectors.[/color]
I think the solution to the indexing problem depends on what the index means
in your problem. I don't see why you can't use iterators, though; I
sometimes use a separate unsigned variable that I increment as I loop
through a container. If you know you are using a vector, then you can use
pointer arithmetic, getting the index by subtracting the begin iterator from
your current position.
[color=blue]
> The possible solutions that I have thought of are:
> 1. Calling a common virtual function of each object through a base
> class pointer, while leaving the virtual function for class C (the
> objects to skip) empty. Cons - Empty member functions seem ugly.[/color]
Why do you think this is ugly? It's the standard OO solution to this
problem. If you start seeing that class C has frequent exceptions like
this, you might reconsider the choice to derive from A, since it cannot
support the full interface. However, if it's an operation that makes sense
to ignore, I don't see the problem. (In fact, if it's a function you expect
only certain derived classes to handle, you could make the implementation
empty in A and it won't even show up in C.)
[color=blue]
> 2. Using run-time type identification (typeid() == typid()) and a
> series of if () else statments to skip the objects of class C. Cons -
> The ensuing if-else tree feels like a botched switch statement.[/color]
It's worse than a botched switch statement, you're doing your own virtual
lookup instead of using the language's built in lookup. Think of it this
way: when a virtual function is called, the program (somehow) decides what
derived function to call from the class's type. Why do you suppose doing
this manually is better than using the built-in feature? Surely, if the
compiler is worth using, it will solve this problem more optimally than you
can. The goal of OO languages was to eliminate this kind of manual type
dispatching.
[color=blue]
> 3. Creating a static data member in each class that holds an int that
> corresponds to the class type. Then, using this value in a switch
> statement to skip over the objects of class C. Cons - I like the
> switch in this step as opposed to solution 2, but it feels wrong
> duplicating type information.[/color]
This has the cons of #2 with some new ones. Notice solutions like this
usually need both a static member of each class to identify the class, and a
virtual function to identify the run-time object. They will need different
names, since C++ doesn't allow virtual and static functions to share a name.
So, this solution requires 3 functions, two of which aren't really related
to the problem at hand; this can contribute to
documentation/understandability issues later on.
[color=blue]
> Am I missing something obvious, or if I'm moving in the right
> direction, which of the solutions is the most elegant? If you're
> feeling especially generous I would love to be told why any of my
> ideas suck and why the best idea is the best.[/color]
#1 is the best. I hope I have explained why.
[color=blue]
> Thanks for any help,
> -Mark[/color]
HTH
--
+---- Kevin C. Saff ----+ F-15 | |Eagle
| Engineer, Boeing, StL | _____|_^_|_____
| Tracking/Fleet Support| * + [_(x)_] + * |  | | | | /bytes/about
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 226,510 network members.
|