在我一年的Qt编程中,我学到了很多关于信号和插槽的知识。但不够..。
http://doc.qt.io/qt-5/signalsandslots.html
插槽可以用来接收信号,但它们也是正常的成员函数。
所以..。是否有任何理由不将继承自QObject的类中的每一个函数声明为一个槽,不管它是否需要一个?
在上面的链接中,他们给出了一个例子:
一个基于QObject的小类可能会读到: #包括类计数器: public QObject { Q_OBJECT public: m_value (){m_value= 0;} int value() const {返回m_value;}公共槽:value( int值);信号: valueChanged(int newValue);
为什么将value()函数定义为普通函数而不是插槽?如果他们做了一个插槽,会有什么负面的结果吗?
发布于 2016-03-09 02:43:29
回到过去,如果你想连接到信号,你别无选择,只能使用插槽。在Qt 5中,这种情况不再是这样,在Qt 5中,可以连接到常规成员函数,甚至是空闲函数或lambda。
将一个插槽注册到该特定对象的元数据中,使其对所有依赖于元对象的Qt功能都可用。除此之外,它是文档声明的常规成员函数。槽函数本身没有什么特别之处,区别在于在元对象中为它生成元数据。
这意味着,在编译时间和可执行文件的大小上,声明插槽都要付出一定的代价,尽管代价很小。我想说的是,把你所有的公共职能都作为插槽太过分了。当您实际需要插槽时,只使用插槽会更有效,如果它不能与常规函数一起工作,则将其设置为一个插槽。
另外,请注意,在几乎所有情况下,信号都是用返回类型void声明的。这与信号的典型使用情况有关--它们通常可以传递参数,但很少返回任何内容。尽管可以通过连接到时隙的信号返回值,但很少使用这种方法。所以声明一个函数作为你要连接的插槽是没有什么意义的,因为它返回一个值意味着它很可能不会在典型的信号/插槽上下文中使用。这就是为什么在这个例子中getter不是一个槽的原因。setter作为一个槽在Qt 5中是多余的,并且可能是这个示例代码的产物,可以追溯到Qt 4。
最后,将插槽从常规的公共函数中分离是说明意图的好方法,如果您愿意的话,也可以说明该类的"API“。例如,在扩展QML时,我主要使用插槽,所以我不必显式地将每个函数标记为可调用函数--与上文提到的情况不同,这些插槽通常返回内容,但它们并不真正用于连接。这样,我就可以清楚地了解这个类提供的接口的设计。
发布于 2016-03-09 07:27:53
除了ddriver的答案,这是最好的/正确的答案(+1在那里),我还会争辩说,将所有成员函数定义为公共槽是令人困惑的。它们定义函数的方式(私有/公共/插槽等)对班级的使用有影响。
我的意思是..。您可能会认为,所有函数都应该是公共的(或公共时隙),然后这涵盖了所有的情况。但是,这可能会使您类的未来用户感到困惑。考虑到int value()是一个公共插槽(这不是最好的例子),有人可以尝试使用它作为一个插槽,但是函数本身有一个返回值,这对插槽没有实际意义。对于普通成员函数(作为正常函数调用),返回值可以被访问,这是很有意义的。
需要遵循的一条规则是始终保持函数和变量尽可能地保持本地范围和私有(默认情况下),并且只打开它们供其他用途(公共性、时隙、全局等)。当你真的需要他们的时候。这使您的类接口更易于理解,并避免了以后用户的混淆。
我确信这个经验法则是有名字的,所以你可以在一些编码技术站点上查找它,但我想不起来了:
编辑
另一个次要的例子是自动完成..。如果您的所有功能都是插槽,那么当您执行connect(this, myClass::mySignal, &someOtherClass, SomeOtherClass::<auto complete options> );时,您的自动完成选项列表可能很长,并且不清楚是什么。如果您只有几个特定的成员是插槽,那么就更容易知道选择哪一个。
发布于 2016-03-09 09:46:54
在引用code_fodder的答案的封装时,应该注意到,实际上没有私有插槽这样的东西。
例如:
class MyClass : public QObject
{
    Q_OBJECT
public:
    MyClass()
        :QObject(NULL) {}
private slots:
    void Hello() { qDebug("Hello World\n"); }
};
#include "main.moc"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyClass* cls = new MyClass;
    QMetaObject::invokeMethod(cls, "Hello");
    return a.exec();
}正如我们在这里看到的,从类外部调用函数Hello是成功的。
https://stackoverflow.com/questions/35879514
复制相似问题