473,804 Members | 3,094 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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 = SomeFactoryMeth od();

Of course SomeFactoryMeth od 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 2093


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 = SomeFactoryMeth od();

Of course SomeFactoryMeth od 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.n etwrote:
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 = SomeFactoryMeth od();
Of course SomeFactoryMeth od 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 AbstractObjectP rocessor
{
public:
virtual ~AbstractObject Processor() {}
virtual void process( B* pObj ) const = 0 ;
} ;

template< typename T >
class ObjectProcessor : public AbstractObjectP rocessor
{
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*,
AbstractObjectP rocessor const*,
TypeInfoCmp map ;

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

template< typename T >
ObjectProcessor ::ObjectProcess or()
{
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 = SomeFactoryMeth od() ;
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 objektorientier ter Datenverarbeitu ng
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.n etwrote:
>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. FactoryMethodFo rC()) 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. FactoryMethodFo rC()) 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. FactoryMethodFo rC()) 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...@ter ra.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. FactoryMethodFo rC()) 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 SomeFactoryMeth od for
choosing the type. If the logic is simple, and based on easily
available data, fine. If not, he may still need to call
SomeFactoryMeth od, 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 objektorientier ter Datenverarbeitu ng
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
15380
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 the same class/static method definition statictly linked to my EXE and when I call InvokeMember(...), even though I got the Type from the new AppDomain, it calls the static method that I am staticly linked to and not the static method in the dynamicly...
4
1740
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 question remaining: How to properly, simple and eleganty implement functions. The functions are encapsulated in the objects, the objects themselves are stored in a binary tree and objects contain 'methods' (functions) along with data. I don't want to...
32
4531
by: Adrian Herscu | last post by:
Hi all, In which circumstances it is appropriate to declare methods as non-virtual? Thanx, Adrian.
5
18156
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 class). Is there a way to do this with reflection? I'm so mad at MS about the CurrencyManager design it makes me want to scream. It's been causing me headaches for months. All of this would be easily fixable if I could create my own...
5
3446
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 5), but fails on IIS 6 running on a Win2003 server. The web uses Pages derived from a custom class I wrote (which itself derives from Page) to provide some common functionality. The Page_Load handler the failing webpage starts out like this: ...
4
2255
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 do is call a generically named public sub in the top-most sub form in the panel. I have the name of the top-most form as a string (eg. g_TopForm = "frmCustomers") and I can reference the form with:
15
2162
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 have an attribute which can be applied to a class definition of a class which inherits from a base, mustinherit class. I want to define methods in the base class which will access the contents of the attribute as it is applied to
8
2027
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 of its own, maybe specifying the liquor store over on 44th Street and 5th Avenue or something. Anyway this is what we have so far: base class: "foo" |------------method: "rob_the_liquor_store()" |
7
2691
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 name based on the name of the VB6 application. A second choice would be a file name based on the # COM interface assembly. I have tried calling Assembly.GetCallingAssembly() but this fails when I use the VB6 client. Is there a way to get this...
0
9704
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9569
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
10558
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
10318
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
10302
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
9130
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
6844
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
5503
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
4277
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.