У меня есть три класса, которые тесно связаны друг с другом, и я хотел бы специализировать все три одновременно. Три производных класса должны взаимодействовать друг с другом с теми же интерфейсами, что и суперклассы, плюс некоторые дополнительные интерфейсы, которые я добавлю в производные версии. Есть ли разумный шаблон, который я могу использовать для реализации такого рода отношений «одновременного вывода» в C ++?
Чтобы быть более конкретным: я расширяю компонент пользовательского интерфейса, который отображает и редактирует график. Участвуют три класса:
Я планирую добавить производные классы CNewGraph, CNewSeries и CNewValue (имена заполнителей).
CGraph ---views/edits---> CSeries ---owns list of---> CValue
^ ^ ^
| is-a | is-a | is-a
| | |
CNewGraph ---views/edits---> CNewSeries ---owns list of---> CNewValue
Проблема, с которой я сталкиваюсь, заключается в том, что, например, CSeries ссылается на CValue в своем определении:
class CSeries
{
public:
CValue & FindValue(/* stuff */);
private:
vector<CValue> m_values;
};
В CNewSeries это должен быть вектор CNewValue, а FindValue должен возвращать ссылку CNewValue и т. Д. Аналогично, CGraph ссылается на CSeries в своем определении, но CNewGraph должен использовать CNewSeries.
Одна из возможностей — шаблонизировать CSeries на основе типа значения. Затем вы можете создать производный класс, который задает определенный тип значения для использования, или даже typedef, если дополнительные члены не нужны.
template <typename T>
class CSeriesBase
{
public:
T & FindValue(/* stuff */);
private:
std::vector<T> m_values;
};
typedef CSeriesBase<CValue> CSeries;
class CNewSeries : public CSeriesBase<CNewValue>
{
/* additional members */
};
Однако это нарушает отношения наследования, поэтому CNewSeries теперь не наследуется от CSeries. Это означает, что все, что использует CSeries, не может беспрепятственно использовать CNewSeries. В частности, на этот раз CGraph также должен быть шаблонизирован по типу серии.
template <typename T>
class CGraphBase
{
public:
void SetSeries(T * pSeries);
private:
T * m_pSeries;
};
typedef CGraphBase<CSeries> CGraph;
class CNewGraph : public CGraphBase<CNewSeries>
{
/* additional members */
};
Только для трех классов это не так уж плохо, хотя я могу вообразить, что это становится громоздким в спешке, если у вас есть еще много классов, нуждающихся в общении с CSeries.
Других решений пока нет …