为什么我们总是从Qt中的基类派生出来?

时间:2012-10-03 21:38:02

标签: qt

当我们使用Qt时,我们总是从Qt类中派生出一个新类,并创建一个新类的实例。例如,为了使用QMainWindow类,我们从QMainWindow派生一个新类,例如名为MW,并从MW中创建一个实例。

我的问题是为什么我们不在这种情况下从QMainWindow基类中创建一个实例?

3 个答案:

答案 0 :(得分:3)

嗯,我多年来一直在使用Qt,甚至从未考虑过这个问题。

我想说如果你可以使用QMainWindow而不进行子类化 - 请继续。但我认为基础QMainWindow类本身的用处相当有限。

我通常在子类中有数百或数千行代码,比如创建菜单,挂钩信号和插槽等等。我不知道如果不在子类中,这段代码在逻辑上会存在。

QMainWindow也可能有纯虚拟,所以你必须覆盖它。但我不知道,从未看过。

希望能回答我所理解的问题。

答案 1 :(得分:1)

您不需要继承QWidget / QMainWindow,但用于创建新项目和新UI文件的QtCreator助手也是如此。

原因很简单:

  1. 它强制执行更清晰的代码。您将此窗口小部件/窗口的行为放在一个类中,而不是在类外。因此,窗口的每个实例都具有相同的行为。如果您只是实例化QWidget / QMainWindow并从外部添加行为(通过连接您需要从外部创建的小部件的信号),那些实例可能会有不同的行为,这显然不是我们所理解的面向对象设计。 / p>

  2. 子窗口小部件可以添加为成员。您应该知道,只有在对类进行子类化时才能将成员添加到类中。不进行子类化将意味着您需要使用窗口小部件/主窗口将这些指针存储在代码中,从而导致代码错误。请注意,您不必存储指向子窗口小部件的指针,因为它们被放入QObject树并由Qt内部管理。但是,如果你有指向这些小部件的指针,那么连接信号,读取QLineEdit等文本中的值等等都会发生。

  3. 处理事件需要子类化[编辑:它也可以使用事件过滤器实现,请参阅注释],因为它们是作为虚拟方法实现的,而不是信号。这还包括自定义绘画,这是通过重新实现虚拟paintEvent来完成的。处理事件还包括对鼠标点击做出反应(除了点击子控件,自己处理它们),鼠标滚轮旋转,按键,最小化和最大化,以及更多。您可以使用信号槽连接处理的Windows上唯一的“操作”是关闭它并请求上下文菜单(右键单击),如果您启用它。所以这两者不一定需要子类化。

  4. 在面向良好的面向对象代码的上下文中更一般地说,创建子类的规则显然如下:

    • 如果你有相同的实例,在相同的输入/属性上表现相同,那么应该属于同一类型

    • 但是只要你有实例的实例,不仅要依赖于不同的输入/属性应该是另一种类型(子类)

    • 只要您需要更改类的某些(已定义的)行为(“覆盖它”)或添加某些成员,必须是另一种类型(子类)

答案 2 :(得分:0)

说一个人应该"总是"子类听起来很危险。我可以在你可以的时候跟随"复合,当你需要时继承#34;

QWidget本身是无用且空洞的,除了在一些可以作为容器的情况下,并且它意味着专门用于实际做某事。

通过从外部添加中央窗口小部件,菜单栏等,可以在没有子类化的情况下完美地使用QMainWindow。由于工具栏按钮,菜单条目等的QAction需要在某处连接,主窗口通常包含作用于这些动作的插槽,这表明子类化。如果它没有失控,有一个连接不同部分的中心位置,提出对话等等是有点自然和好的IMO。即如果主窗口包含比转发动作触发器更多的逻辑并简单地调出对话框,那么应该考虑将该逻辑移出主窗口。

还有许多其他小部件虽然不是为子类设计的,但默认情况下对它们进行子类化没有任何意义,没有充分的理由。 在QLineEdit,QPushButton(QAbstractButton子类,如果你需要一个特殊的按钮),QCheckBox等的子类化中,很少有一点,因为他们不提供可以重新实现以改变行为的特定于小部件的虚拟方法。除非您重新实现虚拟方法,否则组合几乎总是实现目标的更好方法。 是的,有些情况下重新实现fooEvent()可能更直接,然后注册事件过滤器。在那些情况下,这样做,但创建一个" MyLinedit"无论什么时候你需要QLineEdit对我来说都是荒谬和不好的做法。