查看原文
其他

继承和组合,究竟我要选哪个?

程序喵大人 程序喵大人 2022-08-22

[每日一题]栏目第二题,如图:



问题1:想让每个类对象都有一个唯一的ID,有什么优雅的设计?


首先肯定要设计一个管理对象ID的类,即:

struct Object { int64_t GetId();};


那如何将Object与其他类对象关联?可能有这两种方式:

///< 方式1:继承struct A : Object {};
struct B : Object {};
///< 方式2:组合struct A { int64_t GetId() { return obj_.GetId(); }
private: Object obj_;};


继承和组合两种方式?选择哪种更好?



问题2:音视频中,视频基本上包含音频,音频有的属性,视频也有。例如,音频可以设置音量,视频视频包含音频,那我如果也想设置音量,可能有两种方式。


组合方式如下:


struct Audio { void SetVolume();};
struct Video : Audio {};
struct Video { void SetVolume();
private: Audio audio_;};


继承方式如下:


struct Audio { void SetVolume();};
struct Video : Audio {};


那应该怎么选择?


这两个问题其实可以归为一类问题,选择组合还是继承?


tips1:这里说的视频不是音视频专业领域的视频轨,而是我们通常意义上的视频容易,既包含音频轨道也包含视频帧画面。


tips2:也许大家说,这不显而易见吗,区分has a还是 is a,has a就用组合方式,is a就用继承方式。


上面的代码大家也看见了,遵循书本上的说法应该使用组合方式,可如果使用继承方式貌似会非常的方便。


如果Audio类有上百个方法,继承方式几行代码就能搞定,而组合方式,却需要重新在Video上暴露上百个方法,然后在实现中调用Audio的相关方法。(除非把audio变成public成员,变成video.audio.SetVolume,这对用户调用貌似不太友好,用户想要的是直接设置视频音量。)


这貌似很麻烦,我们真的要严格的遵循has a组合、is a继承的定式吗?


组合的缺点:

  • 更多的接口,更多的维护成本。


继承的缺点:

  • 层次过多后,代码可读性差、不好维护


可能很多朋友都厌恶继承,特别是C++中,很多朋友都把继承当作个洪水猛兽,不敢触碰,严格遵循多用组合少用继承的套路。


个人认为,没必要死扣字眼。固定编程范式。


多用组合、少用继承这种定式并不是绝对的,可以根据实际情况适当调整,控制好副作用,发挥各自的优势。


一般使用继承都是为了方便应对频繁变化的需求。但如果继承结构稳定,层次不多,最多两层,那可以大胆的尝试用继承,会更加方便。


回到上面的问题,即便它是has a的关系,但是因为使用组合方式带来的成本过高,而且它的继承层次只有一层,因此我倾向于使用继承方式。


至于has a还是is a,可以改个名字再看一看:


struct Media { void SetVolume();};
struct Audio : Media {};
struct Video : Media {};


嗯,这就是is a了。


以上仅代表个人观点,也不一定对,大家多提宝贵建议哈。



往期推荐



一位大佬对于 Qt 学习的最全总结(三万字干货)

有没有比友元更优雅的方式

压箱底的音视频学习资料以及面经整理

C++ Best Practices (C++最佳实践)翻译与阅读笔记

万字长文 |  STL 算法总结

2021程序喵技术年货

【性能优化】lock-free在召回引擎中的实现

SDK开发的一些思考

防御性编程技巧

C++的全链路追踪方案,稍微有点高端

多线程程序中操作的原子性

喵哥吐血整理:软件开发的51条建议

模版定义一定要写在头文件中吗?



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存