Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 设计模式:继承和封装继承_C++_Inheritance_Design Patterns_Encapsulation - Fatal编程技术网

C++ 设计模式:继承和封装继承

C++ 设计模式:继承和封装继承,c++,inheritance,design-patterns,encapsulation,C++,Inheritance,Design Patterns,Encapsulation,我很难精确地描述它,所以我在标题中留下了更一般的描述(如果你对问题有更精确的描述,请评论,我会编辑标题) 问题:两个类AudioStream和VideoStream是从基类MediaStream派生出来的,它对音频和视频流方法有一些共同之处,但不打算按原样使用。因此,有两个类AudioStreamSettings和VideoStreamSettings,它们派生自mediasstreamsettings,并传递给相应流类的构造函数MediaStreamSettings存储音频和视频的常用设置,基

我很难精确地描述它,所以我在标题中留下了更一般的描述(如果你对问题有更精确的描述,请评论,我会编辑标题)

问题:两个类
AudioStream
VideoStream
是从基类
MediaStream
派生出来的,它对音频和视频流方法有一些共同之处,但不打算按原样使用。因此,有两个类
AudioStreamSettings
VideoStreamSettings
,它们派生自
mediasstreamsettings
,并传递给相应流类的构造函数
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);
  }
}
类媒体流{
公众:
媒体流(常量媒体流设置和设置){
//不执行任何操作,让派生类初始化设置_
//注意:我为这样做感到内疚。。。
}
虚拟~MediaStream(){}
受保护的:
std::共享的ptr设置;
};
类视频流:公共媒体流{
公众:
视频流(const VideoStream设置和设置):
媒体流(设置)
{
设置=标准::使共享(设置);
}
无效剂量测定法(){
int s1=std::dynamic_pointer_cast(设置)->getVideoStreamSetting1();
...
}
};
类音频流:公共媒体流{
公众:
音频流(常量音频流设置和设置):
媒体流(设置)
{
设置=标准::使共享(设置);
}
}
总而言之,我对这种方法中的两件事感到不舒服:

  • 不在基类中初始化
    设置
    (我应该将其抽象化以使自己平静吗?)
  • 每次需要访问派生类中的设置时,使用
    动态\u指针\u cast
    (我应该为此制作一个方法包装器吗?)

  • 一种解决方案是不将数据存储在
    MediaStream
    中,并添加虚拟方法

    virtual const MediaStreamSettings& GetMediaStreamSettings() const = 0;
    

    一种解决方案是不将数据存储在
    MediaStream
    中,并添加虚拟方法

    virtual const MediaStreamSettings& GetMediaStreamSettings() const = 0;
    

    由于MediaStream不应按原样使用,因此将其作为抽象类应该是可以接受的(也是可取的)。 因此,提供实现(包括类成员)是毫无意义的

    class IMediaStream {
    public:
        virtual ~IMediaStream() {}
        virtual void play() = 0;
        virtual std::shared_ptr<MediaSettings> getSettings() = 0;
    private:
        IMediaStream() {}
    };
    
    template<Setting>
    class MediaStream : public IMediaStream {
    public:
        MediaStream(const Setting& settings){
            settings_ = std::make_shared<Setting>(settings);
        }
        virtual ~MediaStream() {}
        virtual void play() override {
            // Implementation here
        }
        virtual std::shared_ptr<MediaSettings> getSettings() override {
            return std::dynamic_pointer_cast<Setting, MediaSettings>();
        }
    private:
        std::shared_ptr<Setting> settings_;
    }
    
    // Alternatively you can inherit or specialize
    // the template to add your implementation
    typedef MediaStream<VideoStreamSettings> VideoStream;
    typedef MediaStream<AudioStreamSettings> AudioStream;
    
    类IMediaStream{
    公众:
    虚拟~IMediaStream(){}
    虚空播放()=0;
    虚拟std::shared_ptr getSettings()=0;
    私人:
    IMediaStream(){}
    };
    模板
    类媒体流:公共媒体流{
    公众:
    MediaStream(常量设置和设置){
    设置=标准::使共享(设置);
    }
    虚拟~MediaStream(){}
    虚拟void play()覆盖{
    //在这里实现
    }
    虚拟std::shared_ptr getSettings()覆盖{
    返回std::dynamic_pointer_cast();
    }
    私人:
    std::共享的ptr设置;
    }
    //或者,您可以继承或专门化
    //用于添加实现的模板
    typedef媒体流视频流;
    typedef媒体流音频流;
    
    由于MediaStream不应按原样使用,因此将其作为抽象类应该是可以接受的(也是可取的)。 因此,提供实现(包括类成员)是毫无意义的

    class IMediaStream {
    public:
        virtual ~IMediaStream() {}
        virtual void play() = 0;
        virtual std::shared_ptr<MediaSettings> getSettings() = 0;
    private:
        IMediaStream() {}
    };
    
    template<Setting>
    class MediaStream : public IMediaStream {
    public:
        MediaStream(const Setting& settings){
            settings_ = std::make_shared<Setting>(settings);
        }
        virtual ~MediaStream() {}
        virtual void play() override {
            // Implementation here
        }
        virtual std::shared_ptr<MediaSettings> getSettings() override {
            return std::dynamic_pointer_cast<Setting, MediaSettings>();
        }
    private:
        std::shared_ptr<Setting> settings_;
    }
    
    // Alternatively you can inherit or specialize
    // the template to add your implementation
    typedef MediaStream<VideoStreamSettings> VideoStream;
    typedef MediaStream<AudioStreamSettings> AudioStream;
    
    类IMediaStream{
    公众:
    虚拟~IMediaStream(){}
    虚空播放()=0;
    虚拟std::shared_ptr getSettings()=0;
    私人:
    IMediaStream(){}
    };
    模板
    类媒体流:公共媒体流{
    公众:
    MediaStream(常量设置和设置){
    设置=标准::使共享(设置);
    }
    虚拟~MediaStream(){}
    虚拟void play()覆盖{
    //在这里实现
    }
    虚拟std::shared_ptr getSettings()覆盖{
    返回std::dynamic_pointer_cast();
    }
    私人:
    std::共享的ptr设置;
    }
    //或者,您可以继承或专门化
    //用于添加实现的模板
    typedef媒体流视频流;
    typedef媒体流音频流;
    
    由于基类提供了
    设置
    数据成员,它应该初始化该成员。然后,它的构造函数应该接受一个参数,该参数要么直接提供完整的设置对象,要么作为工厂来生成它。但是,这里存在的问题是,通过复制创建的多个对象之间可能共享设置。最好让它
    MediaStream
    不可复制。然后一个
    独特的\u ptr
    会更合适。@chearsandhth.-Alf谢谢!起初,我实际上试图使用
    unique\u ptr
    ,但后来却被
    dynamic\u pointer\u cast
    卡住了。我同意,
    shared\u ptr
    在这里不合适。我想结合使用
    unique\u ptr
    和@Jarod42 answer描述的抽象方法将是更好的设计,因为基类提供
    settings
    数据成员,它应该初始化该成员。然后,它的构造函数应该接受一个参数,该参数要么直接提供完整的设置对象,要么作为工厂来生成它。但是,这里存在的问题是,通过复制创建的多个对象之间可能共享设置。最好让它
    MediaStream
    不可复制。然后一个
    独特的\u ptr
    会更合适。@chearsandhth.-Alf谢谢!起初,我实际上试图使用
    unique\u ptr
    ,但后来却被
    dynamic\u pointer\u cast
    卡住了。我同意,
    shared\u ptr
    在这里不合适。我想结合使用
    unique_ptr
    和@Jarod42-answer描述的抽象方法会更好。谢谢!我喜欢这种方法。另外,我将尝试使用
    unique\u ptr
    而不是
    shared\u ptr
    进行
    设置。我会把这个问题保留一段时间,让人们