Как полагают другие, полиморфизм и паттерн Visitor кажутся естественными приспособлениями для этой проблемы.
В C ++ это также можно сделать обобщенно, используя такой класс, как boost::variant
.
Ваш класс Command может быть определен примерно так:
class Command
{
public:
std::vector<boost::variant<KWToken, GOToken> > Toks;
//...
};
, и мы можем определить статический класс посетителя, определяющий операции, выполняемые с каждым типом объекта:
class my_visitor : public boost::static_visitor<void>
{
public:
// define the operation on KWTokens
void operator()(KWToken& tok) const
{
//...
// since tok is well typed, we can access its Synonyms member without any problems.
DoStuff(tok.Synonyms)
}
// and the operation on GOTokens
void operator()(GOToken& tok) const
{
//...
}
};
Изатем, учитывая вариант v
, содержащий один из типов токенов, вы можете вызвать посетителя следующим образом:
boost::apply_visitor( my_visitor(), v );
Подробнее см. http://www.boost.org/doc/libs/1_44_0/doc/html/variant.html.
Это позволяет избежать«традиционный» ООП-полиморфизм, предоставляющий вам полностью основанное на шаблонах решение (использующее статический полиморфизм).
В этом подходе вам даже не нужен общий базовый класс Token
, а конкретные типы токеновне нужно реализовывать какие-либо виртуальные функции.
В C # у вас нет этой опции, и шаблон посетителя (который все еще является правильным решением) должен быть реализован с использованием динамическогополиморфизм.