Why doesn't double dispatch work in C ++?

#include<iostream.h>
#include<conio.h>

using namespace std;

class SpaceShip {};
class GiantSpaceShip : public SpaceShip {};

class Asteroid {
public:
  virtual void CollideWith(SpaceShip *) {
    cout << "Asteroid hit a SpaceShip" << endl;
  }
  virtual void CollideWith(GiantSpaceShip *) {
    cout << "Asteroid hit a GiantSpaceShip" << endl;
  }
};

class ExplodingAsteroid : public Asteroid {
public:
  virtual void CollideWith(SpaceShip *) {
    cout << "ExplodingAsteroid hit a SpaceShip" << endl;
  }
  virtual void CollideWith(GiantSpaceShip *) {
    cout << "ExplodingAsteroid hit a GiantSpaceShip" << endl;
  }
};



int main()
{
  SpaceShip * s = new GiantSpaceShip();    
  Asteroid * a = new ExplodingAsteroid();
  a->CollideWith(s);  
  getch();  

 return 0;   
}

      

How do I enable double dispatch in C ++?

+2


a source to share


2 answers


This is not a separate dispatch, but a double dispatch: you want the method to depend on both the actual / real type of the object it is called on and the actual / actual type of the argument.



This problem can be solved with a visitor design template .

+4


a source


Luke directly using the visitor template, I'm just expanding on this by giving an example of how you could do this.



#include <iostream>
#include <conio.h>

using namespace std;

class SpaceObject;
class SpaceShip;
class GiantSpaceShip;
class Asteroid;
class ExplodingAsteroid;

class SpaceObject {
public:
  virtual void CollideWith(SpaceObject*)       {}
  virtual void CollideWith(SpaceShip*)         {}
  virtual void CollideWith(GiantSpaceShip*)    {}
  virtual void CollideWith(Asteroid*)          {}
  virtual void CollideWith(ExplodingAsteroid*) {}
};



class Asteroid : public SpaceObject {
public:
  virtual void CollideWith(SpaceObject* o)       { o->CollideWith(this); }
  virtual void CollideWith(SpaceShip *)          { cout << "Asteroid hit a SpaceShip" << endl; }
  virtual void CollideWith(GiantSpaceShip *)     { cout << "Asteroid hit a GiantSpaceShip" << endl; }
};

class ExplodingAsteroid : public Asteroid {
public:
  virtual void CollideWith(SpaceObject* o)       { o->CollideWith(this); }
  virtual void CollideWith(SpaceShip *)          { cout << "ExplodingAsteroid hit a SpaceShip" << endl; }
  virtual void CollideWith(GiantSpaceShip *)     { cout << "ExplodingAsteroid hit a GiantSpaceShip" << endl; }
};

class SpaceShip : public SpaceObject {
public:
  virtual void CollideWith(SpaceObject* o)       { o->CollideWith(this); }
  virtual void CollideWith(Asteroid* o)          { o->Asteroid::CollideWith(this); }
  virtual void CollideWith(ExplodingAsteroid* o) { o->ExplodingAsteroid::CollideWith(this); }
};

class GiantSpaceShip : public SpaceShip {
public:
  virtual void CollideWith(SpaceObject* o)       { o->CollideWith(this); }
  virtual void CollideWith(Asteroid* o)          { o->Asteroid::CollideWith(this); }
  virtual void CollideWith(ExplodingAsteroid* o) { o->ExplodingAsteroid::CollideWith(this); }
};

int main()
{
  SpaceObject* s = new GiantSpaceShip();
  SpaceObject* a = new ExplodingAsteroid();
  a->CollideWith(s);
  getch();

 return 0;
}

      

+2


a source







All Articles