C++ Double Dispatch проблемы

Это вторая часть проблемы, которую я ранее задавал: возможно ли перегрузка полиморфного члена в C++?

Используя пример Wiki, я создал этот пример. http://en.wikipedia.org/wiki/Double_dispatch

Моя проблема в том, что скомпилированный код никогда не ищет vtable и всегда использует базу вместо унаследованного класса. Вот мой код:

#include <iostream>

class xEntity;
class xVehicle;

class xMapObject
{
  public:
    virtual void Bump(xMapObject&) { std::cout << "MapObject Bump MapObject\n"; };
    virtual void Bump(xEntity&) { std::cout << "MapObject Bump Entity\n"; };
    virtual void Bump(xVehicle&) { std::cout << "MapObject Bump Vehicle\n"; };
};

class xEntity : public xMapObject
{
  public:
    virtual void Bump(xMapObject&) { std::cout << "Entity Bump MapObject\n"; };
    virtual void Bump(xEntity&) { std::cout << "Entity Bump Entity\n"; };
    virtual void Bump(xVehicle&) { std::cout << "Entity Bump Vehicle\n"; };
};

class xVehicle : public xEntity
{
  public:
    virtual void Bump(xMapObject&) { std::cout << "Vehicle Bump MapObject\n"; };
    virtual void Bump(xEntity&) { std::cout << "Vehicle Bump Entity\n"; };
    virtual void Bump(xVehicle&) { std::cout << "Vehicle Bump Vehicle\n"; };
};

int main(int argv, char **argc)
{
    xEntity Entity;
    xVehicle Vechile;

    xMapObject &EntityRef = Entity;
    xMapObject &VehicleRef = Vechile;

    VehicleRef.Bump(EntityRef);

    return 0;
}

Тем не менее, вывод всегда:

Vehicle Bump MapObject

Любая помощь по этой тайне очень ценится.

3 ответа

Решение

Вы сделали только одну отправку, а не двойную отправку. Идея в том, что в xVehicleвзяв xMapObject&позвонил бы ref.bump(*this); которая является двойной отправкой.

Плохой дизайн xEntity::Bump(xVehicle&), потому что вы используете в качестве параметра в базовом классе производный класс.

и, по крайней мере, если ваш контракт изменился, вам не нужно переопределять базовые методы Bump.

проблема в том, что вы создаете переменные xMapRef, которые преобразуют ваш производный класс в базовый класс.

если вы хотите, чтобы был вызван соответствующий метод, просто вызовите объект производного класса

Он использует vtable; вот почему он звонит xVechicle::Bump()! Vtable не используется для аргументов, это не имеет смысла (по крайней мере, в C++).

Типичным решением является, например, Bump(xMapObject& obj) вызов obj.Bump(*this);,

Другие вопросы по тегам