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*, fncPtr> on 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.