理解继续与组合的本质:Qt 项目中的计划选择指南

[复制链接]
发表于 2025-6-16 12:04:41 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
理解继续与组合的本质:Qt 项目中的计划选择指南

在利用 Qt 举行 C++ 项目开辟时,开辟者常常会遇到如许的困惑:当一个类需要访问另一个类的某个控件或功能时,应该选择继续还是组合?尤其在项目中,我们常常盼望在辅助模块中操作主窗口中的 QMdiArea,这时到底是继续主窗口类还是将 QMdiArea* 通报过去?
这一选择关系到项目布局是否合理、代码是否易于扩展、是否易于维护。因此,理解继续与组合的本质,并在实际项目中做出正确选择,至关重要。
一、继续与组合的本质区别

1. 继续(Inheritance)

继续用于表达“是一个(is-a)”的关系。当子类本身就是父类的一个特化版本,继续是合理且必要的。比方:


  • “学生”是一个“人”
  • “编辑器”是一个“文本控件”
  • “自定义主窗口”是一个“QMainWindow”
在这些场景下,子类继续父类,可以复用父类的功能,并通过重写父类的函数来扩展或修改举动。
2. 组合(Composition)

组合用于表达“有一个(has-a)”或“利用一个(uses-a)”的关系。当一个类只是用到了另一个类的某个成员或功能,而不是其本身的子范例,组合是更合适的选择。比方:


  • “电脑”有一个“CPU”
  • “主窗口”拥有一个“QMdiArea”
  • “文件打开类”利用了“主窗口的 QMdiArea 来添加子窗口”
组合通过将对象作为成员或传参传入,实现机动的对象协作,同时保持各个模块的低耦合。
二、继续的实用场景

以下是继续得当利用的具体场景:

  • 需要复用父类的大量举动和布局。比方自定义控件时,你可能想要继续 QTextEdit 来扩展其举动,如实现特定快捷键、右键菜单等。
  • 需要重写父类的虚函数或变乱处置惩罚函数。如 paintEvent()、mousePressEvent() 等,只有继续父类才能重写这些成员函数。
  • 存在明白的范例从属关系。如果语义上“某类是另一类的子类”,那么利用继续是天然且符合逻辑的。
  • 实现多态接口。如果某个类需要作为基类供多个子类实现多态接口,如 Qt 的插件框架,这时继续是必须的。
示例:
  1. class MyEditor : public QTextEdit {
  2.     // “MyEditor 是一个 QTextEdit”
  3.     void contextMenuEvent(QContextMenuEvent *event) override {
  4.         // 重写默认右键菜单
  5.     }
  6. };
复制代码
三、组合的实用场景

组合更得当以下环境:

  • 只需要利用另一个类的部门功能,而不需要继续其全部接口。这有助于淘汰不必要的耦合。
  • 差异模块之间无“范例层级”关系,仅是功能依赖关系。如主窗口与文件处置惩罚模块之间的关系。
  • 盼望将某些功能抽离成可复用的独立类,方便其他模块调用
  • 在多个对象中利用雷同的成员组件,且需要机动替换或复用
示例:
  1. class FileOpen : public QObject {
  2. public:
  3.     explicit FileOpen(QMdiArea* mdiArea, QObject* parent = nullptr)
  4.         : QObject(parent), m_mdiArea(mdiArea) {}
  5.     void openDocument() {
  6.         QTextEdit* editor = new QTextEdit;
  7.         m_mdiArea->addSubWindow(editor);
  8.         editor->show();
  9.     }
  10. private:
  11.     QMdiArea* m_mdiArea;
  12. };
复制代码
在这个例子中,FileOpen 并不是主窗口,也不需要成为窗口的一部门。它只是利用了主窗口中的 QMdiArea,因此组合是最合适的方式。
四、错误利用继续的后果

在实际项目中,有些开辟者为了访问主窗口中的控件而选择继续主窗口类,比方:
  1. class FileOpen : public Vs_Wps {
  2.     // 继承只是为了访问 ui->mdiArea
  3. };
复制代码
这种做法存在以下严重问题:

  • 违背语义:FileOpen 并不是主窗口的一种范例,不应该“是一个主窗口”。
  • 强耦合:FileOpen 完全绑定在 Vs_Wps 上,无法在其他窗口中复用。
  • 资源冗余:继续主窗口会默认加载所有界面资源,造成浪费。
  • 维护困难:当主窗口布局调整时,FileOpen 会受到不必要的影响。
正确的方式应该是通过构造函数或 setter 方法将 QMdiArea* 通报给 FileOpen,由其独立管理功能逻辑。
五、判断继续或组合的三问法


  • A 是 B 吗?(是 → 继续;不是 → 组合)
  • 我是否要复用 B 的大部门功能?(是 → 继续)
  • 我是否只用到 B 的一个成员或功能?(是 → 组合)
这三个问题可以快速判断计划方向是否正确。
六、继续与组合的对比总结

对比项继续组合语义关系is-a(是一个)has-a / uses-a(有一个/用一个)耦合性高低机动性差高可复用性差好可测试性差好代码维护难(改父类影响子类)易(只影响局部)Qt 中典型场景自定义控件、主窗口模块功能类、逻辑分离类 七、结语

继续与组合是面向对象计划中的底子,也是工程布局清楚与否的关键。错误的继续不但会带来维护困难,还可能造成逻辑混乱和功能耦合。Qt 项目开辟中,尤其保举优先利用组合的方式,让各个模块职责清楚、协作明白。
当我们从“我是否是它”变化为“我是否用它”的头脑时,每每就已经走在了正确计划的道路上。理解计划哲学,比会写代码更重要。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告
回复

使用道具 举报

×
登录参与点评抽奖,加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表