Qt信号和插槽:权限

joh*_*ers 24 c++ inheritance qt signals-slots qt-signals

SO上的尊重答案与实际的Qt文档之间存在差异.

我已经阅读了这个问题,我想进一步澄清一下.有人可以证实:

  • 信号始终是protected,因此它只能由类或其任何子类发出.我不确定这是真的; 上面的问题显示了支持这一陈述的答案.但Qt文档说:Signals are public access functions and can be emitted from anywhere, but we recommend to only emit them from the class that defines the signal and its subclasses.那是什么?
  • 插槽只是功能,因此可以是公共的,私有的或受保护的.显然,如果插槽是公共的,那么外部类能够控制您的类是否将其自身信号之一连接到其自己的插槽之一.然而,SO信息再次与文档不同,文档说:a signal emitted from an instance of an arbitrary class can cause a private slot to be invoked in an instance of an unrelated class.这意味着private信号/插槽机制不尊重它?
  • 使用signal关键字时,public,private,protected这两个词没有用处
  • 发出的信号始终可用于所有其他类,也就是说,任何其他类可能始终连接到该信号(无论其发出信号的权限如何).
  • 尽管所有类都可以查看所有信号,但您仍然可以使用两个具有相同名称信号的类,因为该connect函数将类名称作为信号前缀(即SomeClass::itsSignal)

Fra*_*eld 35

  • 信号在Qt4中受到保护,但在Qt5中是公开的,因此是相互矛盾的信息.
  • 插槽是函数,public/protected/private在调用它们时受到尊重,当连接到信号时,元对象系统会忽略它.
  • signals定义的那样public:,在它们之前加上例如私人潜在客户

至:

private:
public: //signals:
    void theSignal();
Run Code Online (Sandbox Code Playgroud)

因此它没有效果.

  • 所有类都可以连接到任何信号,正确.在这方面,信号是公共API的一部分.
  • 具有相同的信号签名不是问题.上下文由指定为sender的对象定义.

使用旧式连接:

Apple *apple ... Orange* orange
connect(apple, SIGNAL(changed()), this, SLOT(appleChanged()));
connect(orange, SIGNAL(changed()), this, SLOT(orangeChanged()));
Run Code Online (Sandbox Code Playgroud)

该信号被指定为字符串这里(没有在它的类名),但由于appleorange只有一个信号changed()的每个并查找在QObject的情况下,它存在每类(不是实例)之一的元对象做了,他们之间不会发生冲突.

带编译时检查的Qt 5版本:

connect(apple, &Apple::changed, this, &MyReceiver::appleChanged);
Run Code Online (Sandbox Code Playgroud)

这里必须指定一个函数,因此根据范围,必须指定一个类名(可能还有名称空间).由于一个模糊的函数名称不是有效的C++,因此不能编译,所以这里安全.


Seb*_*nge 5

看看qobjectdefs.h(QT5.0 +)。在其中定义了moc宏

#     define signals public
Run Code Online (Sandbox Code Playgroud)

如您所见,信号头文件中使用的宏定义为公共。至于显式状态的public,private,protected指令,在signals部分中将忽略这些指令。QT的先前版本5.0的信号定义为受保护。那些仍然可以使用SIGNAL()宏进行连接。

插槽宏

#     define slots
Run Code Online (Sandbox Code Playgroud)

被定义为空宏,因此可用于:

public slots:
private slots:
protected slots:
Run Code Online (Sandbox Code Playgroud)

方法可见性用于直接方法调用,因此不能直接从外部类调用私有/受保护的方法。

使用a connect语句仍然可以独立于可见性工作。这是预期的行为,并在moc生成的代码中实现。

如果我在Qt的早期版本中没记错的话,插槽也会public自动出现,但是我现在没有找到参考。

任何其他类都可以连接到来自外部类的信号,只要在该类中给出了Q_OBJECT宏并且该外部类是已知的(包括标头)即可。由于信号是按类别定义的,因此在不同类别中使用相同的信号是完全合法的。这也非常方便,例如在所有类中都有一个信号sendInfo(QString)使其更容易记住。Q_OBJECT宏使Moc创建将信号连接到与可见性无关的插槽所需的代码。