Это работает, пока я не вложу шаблон DataMsg в другой DataMsg ... попробую извлечь вложенный DataMsg
Пока ваша логика имеет интуитивный смысл для распаковки вложенных сообщений.
У вас есть общее сообщение с общим заголовком, содержащим конкретное динамическое сообщение определенного типа, извлекает определенную полезную нагрузку сообщения, которое содержит другое сообщение другого определенного типа и т. Д.
Все это прекрасно.
Ваша концептуальная проблема заключается в том, что вы рассматриваете вложенные параметры шаблона как вложенные объекты сообщений, и они совсем не совпадают.
template<typename PayloadType> class DataMsg: public Msg
// ...
private:
PayloadType* pl_;
};
означает каждое создание экземпляра DataMsg
template is-a Msg
и он имеет -a указатель на содержащуюся полезную нагрузку.
Теперь каждый экземпляр DataMsg
является новым типом DataMsg<X>
, который не связан ни с каким другим экземпляром DataMsg<Y>
, даже если X
и Y
связаны (за исключением того, что они оба происходят от Msg
).Итак:
DataMsg<DataMsg<int>>
is-a Msg
и has-a указатель на DataMsg<int>
(который сам is-a Msg
), в то время как
DataMsg<Msg>
также является Msg
, а имеет указатель на Msg
, но все ещеновый тип, не связанный с DataMsg<DataMsg<int>>
(за исключением наличия общей базы), даже если типы указателей полезной нагрузки являются конвертируемыми.
Итак, ваши представления о разметке сообщений хороши, но вы не моделируете их правильно всистема типов.Если вы хотите сделать это, вы можете явно специализироваться на вложенных сообщениях:
using NestedMsg = DataMsg<Msg>;
template<typename NestedPayloadType>
class DataMsg<DataMsg<NestedPayloadType>>: public NestedMsg {
public:
NestedPayloadType const & getDerivedPayload() const
{
// convert nested Msg payload to derived DataMsg
return dynamic_cast<DataMsg<NestedPayloadType> const &>(this->getPayload());
}
};
Сейчас DataMsg<DataMsg<int>>
действительно is-a DataMsg<Msg>
.Как таковой он наследует Msg const& DataMsg<Msg>::getPayload() const
, и вы все равно можете получить производный тип полезной нагрузки (DataMsg<int>
), вызвав `getDerivedPayload ().
Ваш другой метод getPayload
также должен вернуть const ref,КСТАТИ.