【问题标题】:private/public qt signals私人/公共 qt 信号
【发布时间】:2011-01-09 17:37:21
【问题描述】:

Qt 信号可以是公共的还是私有的?我可以创建仅在类内部可见的内部信号吗?

更新:我有一个带有一些内部信号的课程。如何使这些信号对其他类不可见(封装和信息隐藏)?

【问题讨论】:

  • 在这种情况下使用 PIMPL 模式。

标签: qt qt-signals


【解决方案1】:

所有现有答案都不正确。

可以通过在其定义中添加QPrivateSignal 类型作为最后一个参数来将信号设为私有:

signals:
  
  void mySignal(QPrivateSignal);

QPrivateSignalQ_OBJECT宏在每个QObject子类中创建的私有结构,所以只能在当前类中创建QPrivateSignal对象。

从技术上讲,信号仍然具有公共可见性,但它只能由创建它的类发出。

【讨论】:

    【解决方案2】:

    您可以为此使用 PIMPL 模式。您的私有信号仅存在于私有实现中。

    【讨论】:

    • 派生自 QObject 的 PIMPL 不会使其更重并降低性能吗?
    • 是的,这需要一些时间。但请考虑以下问题:调用子程序需要多少时间?相关的程序部分性能是否相关?
    • 不知道为什么这被否决了。我成功地使用了这种方法,例如用于状态机包装器,它在内部使用 QStateMachine 但不公开它(架构原因)。同样,我不想公开用于使状态机进行转换的信号,否则这些信号会与公共 API 信号混合,从而降低可维护性。由于状态机仅根据用户交互进行转换,因此在我的情况下,性能影响完全无关紧要。
    【解决方案3】:

    没有。信号不能是公共的或私有的。 Qt 信号是受保护的类方法。

    “signals”关键字在 qobjectdefs.h 中定义(Qt 4.6.1 的第 69 行):

    #   define signals protected
    

    更新: 信号仅是 protected 直到并包括 Qt 4 的所有次要版本。从 Qt 5.0 开始,它们是 public。见https://stackoverflow.com/a/19130831

    【讨论】:

    【解决方案4】:

    信号在 Qt4 中是 protected,在 Qt5 中它们是 public。 Int Qt5,您可以通过添加 QPrivateSignal 作为最后一个参数来使它们成为 private。更多信息:http://woboq.com/blog/how-qt-signals-slots-work-part2-qt5.html

    【讨论】:

    • 不错的 hack:moc 忽略信号签名中的最后一项,以防名称为 QPrivateSignal
    【解决方案5】:

    一种常见的方式,例如在 kdelibs 中看到,是这样的:

    Q_SIGNALS:
    #ifndef Q_MOC_RUN
        private: // don't tell moc, doxygen or kdevelop, but those signals are in fact private
    #endif
    
       void somePrivateSignal();
    

    这使信号成为私有的,即它只能由类本身发出,而不能由其子类发出。为了不让“private:”覆盖 Q_SIGNALS(然后 moc 不会将 somePrivateSignal 视为信号),它位于 Q_MOC_RUN 内部,仅在 moc 运行时定义。

    编辑:这种方法不适用于 Qt 5 (connect(a, &A::someSignal, b, &B::someSlot)) 引入的新型连接,因为它们要求信号可访问。

    【讨论】:

    • 不,因为“#define Q_SIGNALS protected”,私有:不会有任何影响
    • 德拉特。为什么 C++ 中的一切都需要 hack?
    • "这种方法不适用于 Qt 5 引入的新型连接" -- 取决于...如果只想允许连接到信号在内部也是如此(插槽可能会发出另一个,然后是公共信号),那么这是 理想的 - 除了旧语法仍然允许连接到它......
    【解决方案6】:

    插槽是简单的方法,可以是公共的、受保护的或私有的。

    正如 Andrei 所指出的,信号只是对受保护的重新定义,这意味着它们只能由定义它们的类发出。

    如果你想让一个类从另一个类发出信号,你必须给它添加一个像这样的公共方法(或槽):

    void emitTheSignal(...) {
      emit theSignal(...);
    }
    

    【讨论】:

    • 我认为这不能回答 OP 问题。他指的是只有定义它们的类才能听到的信号。
    • “它们只能由定义它们的类发出” ...或朋友类。 ;)
    • 我不确定这是不是真的。请参阅此处:stackoverflow.com/questions/19129133/… docs cay 信号可以从其他类发出,并且始终是公共的,不受保护。
    • 来自qobjectdefs.h : #define signals protected,所以不,信号不是public
    【解决方案7】:

    Qt 信号是公共的,因为任何对象都可以连接到任何信号。

    【讨论】:

    • 在任何其他类都可以发出它们的意义上,它们也是公共的,因为它们是公共函数。这可能与之前的 Qt 版本有所不同。看这里stackoverflow.com/questions/19129133/…
    • 面向对象编程使用封装来避免访问内部方法和数据。如果信号仅用于内部目的,它们也应该被隐藏。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-11
    • 2014-07-14
    • 1970-01-01
    • 2017-02-17
    • 2012-08-03
    • 2013-01-31
    相关资源
    最近更新 更多