Двойная отправка, не зная полной иерархии - PullRequest
2 голосов
/ 14 апреля 2011

Я хотел бы реализовать следующую вещь в C ++:

Я хотел бы иметь группу дочерних классов одного класса с возможностью вызова функции , которая принимает пару объектов любого из этих типов. Предполагается, что существует универсальная реализация , которая вызывается для смешанных типов или базового типа, и специализированные реализации , которые вызываются, если два объекта одного и того же производного типа используются как аргументы .

Насколько я знаю, это классическое приложение двойная отправка . Однако у меня есть следующее ограничение:

Должна быть возможность извлекать новые классы из существующих и добавлять новые парные функции для этих новых классов без изменения существующих классов , например, во внешней библиотеке.

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

Есть предложения о том, как это реализовать? Это вообще возможно?

Обновление : код говорит более тысячи слов. Работает следующий подход:

#include <iostream>

class B;

class A
{
public:
  virtual void PostCompose(A* other)
    {
      other->PreCompose(this);
    }
  virtual void PreCompose(A* other)
    {
      std::cout << "Precomposing with an A object" << std::endl;
    }
  virtual void PreCompose(B* other);
};

class B : public A
{
public:
  using A::PreCompose;
  virtual void PostCompose(A* other)
    {
      other->PreCompose(this);
    }
  virtual void PostCompose(B* other)
    {
      other->PreCompose(this);
    }
  virtual void PreCompose(B* other)
    {
      std::cout << "Precomposing with a B object" << std::endl;
    }
};

void A::PreCompose(B* other)
  {
    PreCompose((A*)other);
  }

int main()
{
  B b;
  A* p = &b;
  p->PostCompose(p); // -> "Precomposing with a B object"
}

но для реализации A требуется знание B. Есть ли лучший способ?

1 Ответ

1 голос
/ 14 апреля 2011

Поскольку производным классам нужно только определить, соответствует ли тип параметра типу объекта, вы можете просто использовать простую проверку.

virtual void foo( base *argument_base ) {
    if ( derived *argument = dynamic_cast< derived * >( argument_base ) ) {
        argument->something = pair_match_foo;
    } else {
        base_class::foo( argument_base );
    }
}
...