这个问题已经要求在这一论坛,但我不理解这个概念。

我读周围似乎信号,并插槽是实施使用功能的指针。电子信号是一个很大的功能,内部电话都连接隙(功能的指针).这是正确的?和什么作用所产生的交通部文件在整个故事?我不明白的信号如何能知道槽,呼叫我.e其隙都连接到这一信号。

感谢您的时间

有帮助吗?

解决方案

Qt以类似解释语言的方式实现这些东西。即它构造符号表,将信号名称映射到函数指针,维护它们并在需要时按函数名称查找函数指针。

每次发出信号,即写

emit something();

你实际上调用 something()函数,它由元对象编译器自动生成并放入 * .moc 文件中。在此函数中,此时检查此信号连接到哪些插槽,并通过符号表(以上述方式)顺序调用适当的插槽功能(在您自己的源中实现)。与其他特定于Qt的关键字一样, emit 在生成 *。moc 后被C ++预处理器丢弃。实际上,在其中一个Qt标题中( qobjectdefs.h ),存在这样的界限:

#define slots 
#define signals protected
#define emit

连接函数( connect )只修改 * .moc 文件中维护的符号表,以及传递给它的参数(使用 SIGNAL()和`SLOT宏)也被预处理以匹配表。

这是一般的想法。在他或她的另一个答案中,ジョージ 为我们提供链接到trolltech邮件列表另一个问题

其他提示

我觉得我应该加入以下。

那里是 另一个关联的问题 -有 一个很好的文章 这可以被认为是一个相当详细的扩展到它的 答案; 这里是这样的文章了, 与改进的(虽然仍然不完美的)代码的语法突出强调。

这是我的简短复述的,那可以容易出错)

基本上,当我们插入 Q_OBJECT 宏在我们的类定义,预处理器的扩大它对一个静态的 QMetaObject 实例宣言》,将共享所有的实例,同一类:

class ClassName : public QObject // our class definition
{
    static const QMetaObject staticMetaObject; // <--= Q_OBJECT results to this

    // ... signal and slots definitions, other stuff ...

}

这个实例中,反过来,在初始化将储存 签名 ("methodname(argtype1,argtype2)")的信号,并插槽,将允许执行 indexOfMethod() 呼叫,它返回,那么,方法的指数,通过它的签名字符串:

struct Q_CORE_EXPORT QMetaObject
{    
    // ... skip ...
    int indexOfMethod(const char *method) const;
    // ... skip ...
    static void activate(QObject *sender, int signal_index, void **argv);
    // ... skip ...
    struct { // private data
        const QMetaObject *superdata; // links to the parent class, I guess
        const char *stringdata; // basically, "string1\0string2\0..." that contains signatures and other names 
        const uint *data; // the indices for the strings in stringdata and other stuff (e.g. flags)
        // skip
    } d;
};

现在时 moc 创造的 moc_headername.cpp 文件对脱类的头 headername.h, 它把有签名字符串数据和其他数据所必需的正确的初始化 d 结构,并随后写的初始化时代码 staticMetaObject 单独使用这些数据。

另一个重要的事情,它是代码为对象的 qt_metacall() 方法,这需要对象的方法id和一系列参数的指针,并呼吁的方法,通过一个长长的 switch 是这样的:

int ClassName::qt_metacall(..., int _id, void **_args)
{
    // ... skip ...
    switch (_id) {
        case 0: signalOrSlotMethod1(_args[1], _args[2]); break; // for a method with two args
        case 1: signalOrSlotMethod2(_args[1]); break; // for a method with a single argument
        // ... etc ...
    }
    // ... skip ...
}

最后,为每个信号 moc 产生一个执行情况,其中包含一个 QMetaObject::activate() 呼叫:

void ClassName::signalName(argtype1 arg1, argtype2 arg2, /* ... */)
{
    void *_args[] = { 0, // this entry stands for the return value
                      &arg1, // actually, there's a (void*) type conversion
                      &arg2, // in the C++ style
                      // ...
                    };
    QMetaObject::activate( this, 
                           &staticMetaObject, 
                           0, /* this is the signal index in the qt_metacall() map, I suppose */ 
                           _args
                         );
}

最后, connect() 呼叫翻译的字符串的方法的签名,他们整数id(的使用 qt_metacall())和维持一个列表中的信隙连接;当信号发射, activate() 代码就会通过该列表,并呼吁的适当对象"槽"通过他们的 qt_metacall() 法。

总的来说,静 QMetaObject 实例存"的元信息"方法(方法的签名字符串等),生成的 qt_metacall() 方法提供了"一个方法表",允许任何信号/槽被称为通过一个指数,信号的实现产生的 moc 使用这些指标通过 activate(), 和最后 connect() 没有工作保持清单的信隙指数的地图。

*注意:有一种并发症,这个方案使用的情况下,当我们想要传递的信号之间不同的纹(I怀疑,有人要看 blocking_activate() 代码),但是我希望的普遍的想法仍然是相同)

这是我非常粗略的了解相联系的文章,这很容易可能是错误的,因此我建议去读它直接)

PS。因为我想提高我的理解脱执行情况-请让我知道的任何不一致之处在我复述!


因为我其他的(此前)的答案是删除一些热忱的编辑,我将追加的文字在这里(我失踪的几个细节 结合在帕维尔*Shved后,我怀疑的人被删除的答案的关心。)

@帕维尔*Shved:

我非常确定的地方在脱标题存在着一条线:

#define emit

只是来确认:发现它在旧脱码通过谷歌码检索。它是相当可能的,这是仍然存在);找到位置的路径是:

ftp://ftp.slackware-brasil.com.br" 要多得多-7.1" 普" kde-1.90" 脱-2.1.1.解压缩软" usr" lib" 脱-2.1.1" src" 内核" qobjectdefs.h


另一个complementory链接: http://lists.trolltech.com/qt-interest/2007-05/thread00691-0.html -看到答案由安德烈亚斯*Pakulat


这里是另一块的回答: 夸脱的问题:怎么做信号,并插槽工作?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top