У меня есть некоторые общие типы данных и некоторые производный тип (ы):абстрактные классы и шаблоны
class abstract_data { virtual void foo() {}; };
class derived_data : public abstract_data { void foo() {} };
Я хочу написать несколько классов, которые работают над этими данными. Что бы я как сделать это:
class abstract_worker {
public:
virtual void apply(abstract_data&) = 0;
};
class derived_worker : public abstract_worker {
public:
void apply(derived_data&) {} ;
};
Это не работает, потому что компилятор просит меня реализовать void apply(abstract_data&)
. Я вижу две альтернативы.
1.alternative:
class abstract_worker {
public:
virtual void apply(abstract_data&) = 0;
};
class derived_worker : public abstract_worker {
public:
void apply(abstract_data& data) {
derived_data& internal_data = dynamic_cast<derived_data&>(data);
}
};
2. альтернатива:
template<class DATA_TYPE>
class abstract_worker {
public:
virtual void apply(DATA_TYPE&) = 0;
};
class derived_worker : public abstract_worker<derived_data> {
public:
void apply(derived_data&) { }
};
Я не люблю их обоих. В 1-й альтернативе параметр объявляется как abstract_data&
, хотя он действительно должен быть derived_data&
.
Во второй альтернативе теряется, что параметр имеет тип abstract_data&
. Это еще более проблематично, если apply(abstract_data&)
не является чисто виртуальным, но использует некоторую функциональность abstract_data
. Вы запускаете в situtation, где abstract_data&
неявно требуется как DATA_TYPE
, но явно не объявлено как таковое.
Однако я хочу сохранить отношения типа.
Есть ли другой способ? Если бы не тот, который вы бы предпочли?
Первый укладывается в общую философии виртуальных функций. Второе - нет. Трудно представить, почему было бы полезно иметь это как виртуальную функцию и иметь вторую иерархию. Когда вам нужен такой шаблон, это обычно вместо виртуального, не смешанного таким образом. – JSF
Ваш предпочтительный 'производный_работник' не соответствует Принципу замещения Лискова, что указывает на плохой дизайн. Почему «производный_оператор» является «абстрактным_работником», если все «абстрактные_работники» могут работать со всеми «абстрактными_датами», а «производный_работник» не может? – Angew
Это не место для использования виртуальных функций. Они предназначены для тех случаев, когда вы не знаете динамический тип объекта. Ваш производный работник знает, что он хочет получить производного. –