473,385 Members | 1,610 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.

Double Dispatch Obsolete?

Since I started with OO I've been told switching on typeid is a big
no-no. E.g.

void Washer::wash( Vehicle myVehicle )
{
if( typeid(myVehicle) == typeid(Car) )
Washer::washCar( myVehicle );
else if( typeid(myVehicle) == typeid(Bike)
Washer::washBike( myVehicle );
else if( typeid(myVehicle) == typeid(Boat)
Washer::washBoat( myVehicle );
}

The alternative is the more correct Double Dispatch. E.g.

void Washer::wash( Vehicle myVehicle )
{
myVehicle.washer( this )
}

void Car::washer( Washer w )
{
w.washCar( this );
}

Now, consider we change Washer to XMLConverter and wash() to write().
This will still work, but when we want to go backwards and read XML and
write a Vehicle we need to switch on some kind of type id label anyway. E.g.

Vehicle XMLConverter::readVehicle( XMLdoc doc )
{
Vehicle v;
string s = doc.readAttr();
if( s == "Car" )
v = new Car();
else if( s == "Bike" )
v = new Bike();
else if( s == "Boat" )
v = new Boat();

return v;
}

So why not just give every MyObject a typeName() method and switch or
std::map<char*, fncPtron that throughout all dispatchers?
//Daniel


Sep 4 '07 #1
2 3224
DeMarcus wrote:
Since I started with OO I've been told switching on typeid is a big
no-no. E.g.

void Washer::wash( Vehicle myVehicle )
{
if( typeid(myVehicle) == typeid(Car) )
Washer::washCar( myVehicle );
else if( typeid(myVehicle) == typeid(Bike)
Washer::washBike( myVehicle );
else if( typeid(myVehicle) == typeid(Boat)
Washer::washBoat( myVehicle );
}
Yes - no-no - not extensible. Code like this tends to proliferate and
is prone to error.
>
The alternative is the more correct Double Dispatch. E.g.

void Washer::wash( Vehicle myVehicle )
{
myVehicle.washer( this )
}

void Car::washer( Washer w )
{
w.washCar( this );
}
Kind of.

It would be more like:

myVehicle.DoSomthing( Wash ).

void Car::DoSomthing( Dispatcher & i_dispatch )
{
i_dispatch.WashCar( * this );
}
>
Now, consider we change Washer to XMLConverter and wash() to write().
This will still work, but when we want to go backwards and read XML and
write a Vehicle we need to switch on some kind of type id label anyway.
E.g.

Vehicle XMLConverter::readVehicle( XMLdoc doc )
{
Vehicle v;
string s = doc.readAttr();
if( s == "Car" )
v = new Car();
else if( s == "Bike" )
v = new Bike();
else if( s == "Boat" )
v = new Boat();

return v;
}
This is usually solved by a generic factory system like Austria C++'s
factory thing.

v = at::FactoryRegister< Interface, std::string >::Get().Create( s )();
>
So why not just give every MyObject a typeName() method and switch or
std::map<char*, fncPtron that throughout all dispatchers?
That can be one way. If done correctly, the double dispatch technique
is able to pick up when you miss a case by using pure virtual methods.
In this example if a new type of vehicle is make and the method is not
implemented, it can cause a compile time error which can flag missing
actions.

Sep 4 '07 #2
On 2007-09-04, DeMarcus <no****@tellus.netwrote:
The alternative is the more correct Double Dispatch. E.g.

void Washer::wash( Vehicle myVehicle )
{
myVehicle.washer( this )
}
This isn't double dispatch, the parameter is being passed by value so
if you are attempting to pass in something derived from Vehicle, this
will be "sliced" into a base Vehicle in any case.
>
void Car::washer( Washer w )
{
w.washCar( this );
}
OK, but this won't get called by the function above.
Now, consider we change Washer to XMLConverter and wash() to write().
This will still work, but when we want to go backwards and read XML and
write a Vehicle we need to switch on some kind of type id label anyway. E.g.

Vehicle XMLConverter::readVehicle( XMLdoc doc )
{
Vehicle v;
string s = doc.readAttr();
if( s == "Car" )
v = new Car();
else if( s == "Bike" )
v = new Bike();
else if( s == "Boat" )
v = new Boat();

return v;
}
When you are creating new objects from a serialized form you do have
to workout exactly what type of object you want to create. This has
to involve some sort of interpretation of a flat data format an making
a decision based on that. Again, this code appears to be wrong. The
return type is returning Vehicle by value, so whatever derived type is
created in the method, only a base Vehicle can be returned. The local
variable v is an object type, not a pointer, so unless the base
Vehicle class has a very unusual form of assignment operator taking a
pointer to Vehicle or derived type then this won't compile.
So why not just give every MyObject a typeName() method and switch or
std::map<char*, fncPtron that throughout all dispatchers?
A std::map of char* might not do what you think it does. You'd have
to find the char* in a fixed list of char* that matched the string
which you were looking for, where the fixed list was known to be the
actually char* which were used in creating the map. std::map<char*...
will be sorted by pointer value, not string value. Also, you can only
use a switch with integral or enumeration types, so you would still
need a method to convert a string to such a type.

Sep 4 '07 #3

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

Similar topics

1
by: Thomas Matthews | last post by:
Hi, I'm looking for an efficient method to deep copy containers of fields. A Field is a parent class with children such as Integer_Field, String_Field, and Date_Field, etc. The algorithm /...
3
by: Dan Vogel | last post by:
I'd like to find an elegant solution to the problem of calling a certain function based on the types of two parameters. In my case, the functions compute the distance between different types of...
1
by: AndyL | last post by:
Hi, Where I can find a module supporting that? A.
55
by: Martin Jørgensen | last post by:
Hi, I found the code below from http://www.blitzbasic.com/Community/posts.php?topic=55633 ------ ' Check if number is finite. Local u:Double = 2 ' also works for floats
3
by: tyler.schlosser | last post by:
Hi there, I am trying to launch a program called AmiBroker using the command: AB = win32com.client.Dispatch("Broker.Application") However, I have a dual-core CPU and would like to launch two...
3
by: Tigera | last post by:
Greetings, I too have succumbed to the perhaps foolish urge to write a video game, and I have been struggling with the implementation of multiple dispatch. I read through "More Effective C++"...
0
by: learning | last post by:
hi, is there a way to make a function dispatch table in C#? Purpose: I have am using Microsoft web test to automate web testing. the web test generated are all a collection declarative...
2
by: mark4asp | last post by:
In trying to get the C# conversion code for Head First Design Patterns to work I came accross a number of warnings. e.g. Warning Number: 10 Description: ...
6
by: saneman | last post by:
I am trying to use double dispatch in the below code: #include <iostream> class Box; class Sphere; class geometry_type {
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
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: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
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?
0
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,...
0
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...
0
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,...

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.