Правильное использование унаследованных классов
У меня есть проблема, с которой я борюсь уже 2 дня. Проблема заключается в том, что мне нужно написать логику для получения настроек мультимедиа из унаследованного класса. Чтобы полностью понять, что именно я хочу реализовать, приведу краткий пример.
У меня есть интерфейс:
class MediaSettings
{
public:
MediaSettings(QString mediaType);
MediaSettings& operator=(const MediaSettings& other) = delete;
MediaSettings& operator=(MediaSettings&& other) = delete;
MediaSettings(const MediaSettings& other) = delete;
MediaSettings(MediaSettings&& other) = delete;
virtual ~MediaSettings() = default;
QString getType() { return m_mediaType; }
virtual bool isSupported() const noexcept = 0;
protected:
QString m_mediaType{ "UNK" };
};
И два класса, которые содержут в себе определенные поля настроек мультимедиа, а именно класс AudioSettings и VideoSettings.
AudioSettings:
class AudioSettings : public MediaSettings
{
public:
explicit AudioSettings(const int32_t& bitRate, const int32_t& sampleRate, const int32_t& channelCount, const QString& audioCodec)
: MediaSettings("audio")
{
}
AudioSettings& operator=(const AudioSettings& other) = default;
AudioSettings& operator=(AudioSettings&& other) = default;
AudioSettings(const AudioSettings& other) = default;
AudioSettings(AudioSettings&& other) = default;
virtual ~AudioSettings() = default;
bool operator==(const AudioSettings& other) const noexcept;
bool operator!=(const AudioSettings& other) const noexcept;
void setChannelCount(const int32_t& channelCount) noexcept;
void setSampleRate(const int32_t& sampleRate) noexcept;
void setAudioCodec(const QString& audioCodec) noexcept;
void setBitRate(const int32_t& bitRate) noexcept;
int32_t channelCount() const noexcept;
QString audioCodec() const noexcept;
int32_t sampleRate() const noexcept;
int32_t bitRate() const noexcept;
virtual bool isSupported() const noexcept override;
protected:
int32_t m_bitRate{ -1 };
int32_t m_sampleRate{ -1 };
int32_t m_channelCount{ -1 };
QString m_audioCodec;
};
VideoSettings:
class VideoSettings : public MediaSettings
{
public:
explicit VideoSettings(const int32_t& width, const int32_t& height, const QString& videoCodec)
: MediaSettings("video")
{
}
VideoSettings& operator=(const VideoSettings& other) = default;
VideoSettings& operator=(VideoSettings&& other) = default;
VideoSettings(const VideoSettings& other) = default;
VideoSettings(VideoSettings&& other) = default;
virtual ~VideoSettings() = default;
bool operator==(const VideoSettings& other) const noexcept;
bool operator!=(const VideoSettings& other) const noexcept;
int32_t width() const noexcept;
int32_t height() const noexcept;
QString videoCodec() const noexcept;
void setWidth(const int32_t& width) noexcept;
void setHeight(const int32_t& height) noexcept;
void setVideoCodec(const QString& videoCodec) noexcept;
virtual bool isSupported() const noexcept override;
protected:
int32_t m_width{ -1 };
int32_t m_height{ -1 };
QString m_videoCodec;
};
И вот тут-то и возникает моя главная проблема. У меня есть класс MediaRecorder, который имеет метод установки медиа настроек:
class MediaRecorder
{
public:
MediaRecorder();
virtual ~MediaRecorder();
bool record(const MediaData data);
bool start();
bool stop();
void setMediaSettings(MediaSettings* settings) noexcept;
// Какие-то функции
protected:
// Какие-то параметры
MediaSettings* p_settings;
};
И в этом классе есть параметры, которые, в свою очередь, могут одновременно ожидать как настройки звука, так и настройки видео. В качестве примера, при установке аудио настроек, данный рекордер должен работать с методами, описанными в классе AudioSettings:
// main.cpp
// Создаем рекордер
MediaRecorder recorder;
// Устанавливаем ему настройки для аудио
recorder.setMediaSettings(new AudioSettings(64000, 8000, 1, "alaw"));
реализация метола setMediaSettings:
void MediaRecorder::setMediaSettings(MediaSettings* settings) noexcept
{
if (settings) {
if (settings.getType() == "audio") {
auto audioSettings = reinterpret_cast<AudioSettings>(settings);
// Работаем с методами AudioSettings
int bitrate = audioSettings.bitRate();
// ...
}
else if (settings.getType() == "video") {
auto videoSettings = reinterpret_cast<VideoSettings>(settings);
// Работаем с методами AudioSettings
int width = videoSettings.width();
// ...
}
else {
// Error
}
}
}
Правильно ли реализована логика определения типа наследуемого класса ? А если нет, то не могли бы вы объяснить мне, как это правильно реализовать?
Ответы (1 шт):
Если уж базовый класс является интерфейсным(абстрактный), то перенесите интерфейс в базовый класс, а в производных переопределите те функции_члены, которые нужны этому классу, тогда можете через указатель на базовый класс вызвать функцию указываемого объекта. Первоначально это может выглядеть следующим образом:
class MediaSettings
{
//...
public:
virtual bool isSupported() const noexcept = 0;
virtual int32_t bitRate() const noexcept { return 0; }
virtual int32_t width() const noexcept { return 0; }
virtual int32_t height() const noexcept { return 0; }
//...
bool is_audio{}; //если вам нужно
};
class AudioSettings : public MediaSettings
{
//...
public:
AudioSettings() { is_audio = true; } //если вам нужен был is_audio
//...
int32_t bitRate() const noexcept override { //... }
virtual bool isSupported() const noexcept { //... }
//...
};
class VideoSettings : public MediaSettings
{
//...
public:
int32_t width() const noexcept override{ //... }
int32_t height() const noexcept override { //... }
bool isSupported() const noexcept { //... }
//...
};
class MediaRecorder
{
//...
public:
void setMediaSettings(MediaSettings* settings) noexcept
{
int32_t bitrate{}, width{};
if (settings) {
bitrate = settings->bitRate();
width = settings->width();
if (bitrate /* или settings->is_audio */) {
// Работаем с методами AudioSettings
}
else if (width) {
// Работаем с методами VideoSettings
}
}
}
// ...
};