473,385 Members | 1,347 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,385 software developers and data experts.

Calling methods based on derived type

Hi,

Say I have a baseclass B that has many derived classes, let's say
C..Z, for example:

class B
{
};

class C : public B {};
class D : public B {};
class E : public B {};
....

Also assume that these classes are provided as is, that is, I can not
make any changes to them (the real classes contain many data members,
etc).

Now, there is a factory method that creates the correct class based on
input from some external source. Something like:

B *b = SomeFactoryMethod();

Of course SomeFactoryMethod will actually return any of the dervied
classes depending on the external information.

Now here is my question. There are a set of methods such as:

processObject(C *);
processObject(D *);
processObject(E *);
.... for all derived types.

Given the base clas pointer returned from the factory, how can I call
the correct method? Obviously I can have a bunch of dynamic_cast<>'s
but that does not seem the best way. I was thinking I could do
something with templates and typeinfo?

Any ideas? Please remember that I can not change the existing classes.

Apr 26 '07 #1
9 2072


Take a look at "virtual" keyword.
Apr 26 '07 #2
flopbucket wrote:
Say I have a baseclass B that has many derived classes, let's say
C..Z, for example:

class B
{
};

class C : public B {};
class D : public B {};
class E : public B {};
...

Also assume that these classes are provided as is, that is, I can not
make any changes to them (the real classes contain many data members,
etc).

Now, there is a factory method that creates the correct class based on
input from some external source. Something like:

B *b = SomeFactoryMethod();

Of course SomeFactoryMethod will actually return any of the dervied
classes depending on the external information.

Now here is my question. There are a set of methods such as:

processObject(C *);
processObject(D *);
processObject(E *);
... for all derived types.

Given the base clas pointer returned from the factory, how can I call
the correct method? Obviously I can have a bunch of dynamic_cast<>'s
but that does not seem the best way.
I think that's the only way available. Wrap it in a function and you
are going to have a very clear and concise way. I would even create
some kind of table for either using in a 'switch' statement or for
dispatching the call (through a function pointer).
I was thinking I could do
something with templates and typeinfo?
I don't see how it's better. 'typeid' will give you the most derived
class. What if somebody derives something from 'C' (making 'CC' class)
so you won't be able to compare type_info for 'C' with it. 'dynamic_cast',
OTOH will definitely tell you whether the class is part of the hierarchy.
Any ideas? Please remember that I can not change the existing
classes.
I believe you'd be better off with dynamic_cast (or something based on
it).

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Apr 26 '07 #3
Gernot Frisch wrote:
Take a look at "virtual" keyword.
He is not allowed to change the classes, remember? Besides,
the classes are already polymorphic, otherwise he wouldn't
be talking of 'dynamic_cast'...
Apr 26 '07 #4
On Apr 26, 11:28 am, "Gernot Frisch" <M...@Privacy.netwrote:
Take a look at "virtual" keyword.
virtual has nothing to do with his - the methods are NOT members of
the class, they are either stand alone functions of members of another
class. It is as if the calls need to be virtual based on the
parameter typeinfo and not the calling class pointer.
Apr 26 '07 #5
flopbucket wrote:
Say I have a baseclass B that has many derived classes, let's say
C..Z, for example:
class B
{
};
class C : public B {};
class D : public B {};
class E : public B {};
...
Also assume that these classes are provided as is, that is, I can not
make any changes to them (the real classes contain many data members,
etc).
Now, there is a factory method that creates the correct class based on
input from some external source. Something like:
B *b = SomeFactoryMethod();
Of course SomeFactoryMethod will actually return any of the dervied
classes depending on the external information.
Now here is my question. There are a set of methods such as:
processObject(C *);
processObject(D *);
processObject(E *);
... for all derived types.
Given the base clas pointer returned from the factory, how can I call
the correct method? Obviously I can have a bunch of dynamic_cast<>'s
but that does not seem the best way. I was thinking I could do
something with templates and typeinfo?
Any ideas? Please remember that I can not change the existing classes.
If you cannot change the existing classes nor the factory
function, then you'll have to maintain a parallel hierarchy,
something like:

class AbstractObjectProcessor
{
public:
virtual ~AbstractObjectProcessor() {}
virtual void process( B* pObj ) const = 0 ;
} ;

template< typename T >
class ObjectProcessor : public AbstractObjectProcessor
{
public:
virtual void process( B* pObj ) const
{
assert( dynamic_cast< T* >( pObj ) != NULL ) ;
processObject( static_cast< T* >( pObj ) ) ;
}
} ;

Then, a static object for each type, and to find it:

struct TypeInfoCmp
{
bool operator()(
std::type_info const* lhs,
std::type_info const& rhs ) const
{
return lhs->before( *rhs ) ;
}

} ;
std::map< std::type_info const*,
AbstractObjectProcessor const*,
TypeInfoCmp map ;

In such cases, I'll often add a constructor to the template:

template< typename T >
ObjectProcessor::ObjectProcessor()
{
map[ &typeid( T ) ] = this ;
}

Be careful about the order of initialization if you do this;
either the map must be wrapped in a singleton, or you'll have to
put all of the static instances in the same file, after the map.

To call the function, of course:

B* pB = SomeFactoryMethod() ;
map[ &typeid( *pB ) ]->process( pB ) ;

Note too that anytime someone adds a derived class, you'll have
to add a static ObjectProcessor object.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Apr 27 '07 #6
On 26 Apr 2007 12:04:56 -0700, flopbucket wrote:
>On Apr 26, 11:28 am, "Gernot Frisch" <M...@Privacy.netwrote:
>Take a look at "virtual" keyword.

virtual has nothing to do with his - the methods are NOT members of
the class, they are either stand alone functions of members of another
class. It is as if the calls need to be virtual based on the
parameter typeinfo and not the calling class pointer.
I guess that you have written the processObject() functions. Your
difficulty exhibits a design problem rather than an implementation
problem. Your FactoryMethod returns a pointer to an interface (B). In
'classic' OOP style you are supposed to program against the interface,
not an implementation (C, D, E, ...). The problem can be solved by
either re-writing the processObject() functions to one function that
accepts the interface (processObject(B*)) or by writing special
factory methods for derived classes (e.g. FactoryMethodForC()) and
preserve the type information throughout the program. The latter is of
course 'less OO'.
--
Roland Pibinger
"The best software is simple, elegant, and full of drama" - Grady Booch
Apr 27 '07 #7
I guess that you have written the processObject() functions. Your
difficulty exhibits a design problem rather than an implementation
problem. Your FactoryMethod returns a pointer to an interface (B). In
'classic' OOP style you are supposed to program against the interface,
not an implementation (C, D, E, ...). The problem can be solved by
either re-writing the processObject() functions to one function that
accepts the interface (processObject(B*)) or by writing special
factory methods for derived classes (e.g. FactoryMethodForC()) and
preserve the type information throughout the program. The latter is of
course 'less OO'.

--
Roland Pibinger
"The best software is simple, elegant, and full of drama" - Grady Booch
Well, actually I didn't write either, but am tasked with glueing the
two together. The processObject() methods already exist from a legacy
application, and I need to call the correct one based on the object
created by the factory.

Apr 27 '07 #8
flopbucket wrote:
>I guess that you have written the processObject() functions. Your
difficulty exhibits a design problem rather than an implementation
problem. Your FactoryMethod returns a pointer to an interface (B). In
'classic' OOP style you are supposed to program against the interface,
not an implementation (C, D, E, ...). The problem can be solved by
either re-writing the processObject() functions to one function that
accepts the interface (processObject(B*)) or by writing special
factory methods for derived classes (e.g. FactoryMethodForC()) and
preserve the type information throughout the program. The latter is of
course 'less OO'.
Well, actually I didn't write either, but am tasked with glueing the
two together. The processObject() methods already exist from a legacy
application, and I need to call the correct one based on the object
created by the factory.
You can create a new hierarchy of classes, a base with all member functions
required in the original interface, and a processObject virtual member, and
derived classes with his own processObject member that call corresponding
the non-member processObject function. Then make a factory that return
object from this hierarchy that contains (or have a pointer, smart pointer,
whatever way you want) the corresponding object in the original hierarchy.
The drawback is that you have a lot of boring code to write.

--
Salu2
Apr 27 '07 #9
On Apr 27, 4:09 pm, Julián Albo <JULIANA...@terra.eswrote:
flopbucket wrote:
I guess that you have written the processObject() functions. Your
difficulty exhibits a design problem rather than an implementation
problem. Your FactoryMethod returns a pointer to an interface (B). In
'classic' OOP style you are supposed to program against the interface,
not an implementation (C, D, E, ...). The problem can be solved by
either re-writing the processObject() functions to one function that
accepts the interface (processObject(B*)) or by writing special
factory methods for derived classes (e.g. FactoryMethodForC()) and
preserve the type information throughout the program. The latter is of
course 'less OO'.
Well, actually I didn't write either, but am tasked with glueing the
two together. The processObject() methods already exist from a legacy
application, and I need to call the correct one based on the object
created by the factory.
You can create a new hierarchy of classes, a base with all member functions
required in the original interface, and a processObject virtual member, and
derived classes with his own processObject member that call corresponding
the non-member processObject function. Then make a factory that return
object from this hierarchy that contains (or have a pointer, smart pointer,
whatever way you want) the corresponding object in the original hierarchy.
The drawback is that you have a lot of boring code to write.
Not that much, really, since all you need is a template, and to
instantiate that. On the other hand, he will have to duplicate
whatever logic is currently present in SomeFactoryMethod for
choosing the type. If the logic is simple, and based on easily
available data, fine. If not, he may still need to call
SomeFactoryMethod, obtain whatever type, and then use a map to
determine which of his types he needs to create.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Apr 27 '07 #10

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

Similar topics

5
by: Chris | last post by:
Hi I have a scenario where I've created another AppDomain to dynamically load a DLL(s) into. In this newly loaded DLL I want to call a static method on a class. The problem arise is that I have...
4
by: Gibby Koldenhof | last post by:
Hiya, I'm setting up some code in the spirit of Design Patterns, OOP, etc. All nice and well, it handles pretty much all OO style things and serves my purposes well. There's one last final...
32
by: Adrian Herscu | last post by:
Hi all, In which circumstances it is appropriate to declare methods as non-virtual? Thanx, Adrian.
5
by: Pete Davis | last post by:
I know I can use reflection to call internal, protected, and private methods in a class, but I need to instantiate an object that is public but has an internal constructor (The CurrencyManager...
5
by: Nick Flandry | last post by:
I'm running into an Invalid Cast Exception on an ASP.NET application that runs fine in my development environment (Win2K server running IIS 5) and a test environment (also Win2K server running IIS...
4
by: Bugs | last post by:
Hi, I wonder if anyone can help me out. I'm building a vb.net application that has a form with a panel that contains several other sub forms (as a collection of controls). What I'm wanting to...
15
by: Jeff Mason | last post by:
Hi, I'm having a reflection brain fog here, perhaps someone can set me on the right track. I'd like to define a custom attribute to be used in a class hierarchy. What I want to do is to...
8
by: Mike C# | last post by:
Suppose I have a base class "foo". Another class, "bar" derives from it. Base class "foo" has a method called "rob_the_liquor_store()", and the inherited class "bar" overrides this method with one...
7
by: =?Utf-8?B?UVNJRGV2ZWxvcGVy?= | last post by:
I have a C# logging assembly with a static constructor and methods that is called from another C# Assembly that is used as a COM interface for a VB6 Application. Ideally I need to build a file...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

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.