У меня возникли проблемы с его формулировкой, поэтому я оставил более общее описание в названии (если у вас есть более точное описание проблемы, прокомментируйте, я отредактирую название).Дизайн шаблона: наследование и инкапсулированное наследование
Проблема: Два класса AudioStream
10 и VideoStream
получены из базового класса MediaStream
, который имеет некоторые общие для аудио- и видеопотоков методы, но не предназначен для использования как есть. Следовательно, существуют два класса AudioStreamSettings
и VideoStreamSettings
, которые получены из MediaStreamSettings
и переданы конструкторам соответствующих классов потоков. MediaStreamSettings
сохраняет настройки, общие для аудио и видео, а базовый класс MediaStream
обращается к этим данным. Вопрос в том, что было бы лучшим способом для разработки этой иерархической связи между базовыми классами потоков и настроек?
Я могу придумать быстрого решения, как следующее:
class MediaStream {
public:
MediaStream(const MediaStreamSettings& settings){
// do nothing, let derived classes initialize settings_
// note: I feel guilty for doing this...
}
virtual ~MediaStream(){}
protected:
std::shared_ptr<MediaStreamSettings> settings_;
};
class VideoStream : public MediaStream {
public:
VideoStream(const VideoStreamSettings& settings):
MediaStream(settings)
{
settings_ = std::make_shared<VideoStreamSettings>(settings);
}
void doSomething(){
int s1 = std::dynamic_pointer_cast<VideoStream, MediaStream>(settings_)->getVideoStreamSetting1();
...
}
};
class AudioStream : public MediaStream {
public:
AudioStream(const AudioStreamSettings& settings):
MediaStream(settings)
{
settings_ = std::make_shared<AudioStreamSettings>(settings);
}
}
Резюмируя Я не комфортно с двумя вещами в этом подходе:
- не инициализирующих
settings_
в базовом классе (следует Я делаю это абстрактным, чтобы успокоиться?) - с использованием
dynamic_pointer_cast
каждый раз, когда мне нужно получить доступ к настройкам в производных классах (должен ли я сделать оболочку метода для этого?)
Поскольку базовый класс предоставляет член данных 'settings_', он должен инициализировать этот элемент. Его конструктор должен затем принять аргумент, который либо предоставляет полный объект настроек напрямую, либо служит в качестве фабрики для его создания. Тем не менее, проблематичным здесь является потенциальное совместное использование настроек между несколькими объектами, созданными при копировании. Лучше сделайте этот «MediaStream» не скопированным. И тогда «unique_ptr» будет лучше подходит. –
@ Cheersandhth.-Alf спасибо! во-первых, я на самом деле пытался использовать 'unique_ptr', но затем застрял с' dynamic_pointer_cast' для этого. Я согласен, 'shared_ptr' здесь не подходит. Я предполагаю, что комбинация «unique_ptr» и абстрактного метода, описанная в ответе @ Jarod42, будет лучшим дизайном – peetonn