回调的缺陷

Callback's flaws

本文关键字:缺陷 回调      更新时间:2023-10-16

From: http://doc.qt.nokia.com/4.7/signalsandslots.html

回调有两个基本缺陷:首先,它们不是类型安全的。我们永远不能确定的是处理函数将调用使用正确的参数回调。

谁能给我解释一下,在什么样的情况下,论点不确定是正确的?这句话的技术要点是什么?

编辑1 正如Gui13在下面的帖子中指出的那样,当传递char*时,QString确实会给出错误。但是我测试了下面的程序:

#include <iostream>
#include <QString>
#include <stdio.h>
typedef int (*callback_function)( QString *string);
int MyCallback( std::string string )
{
    if (string.empty() == false)
        std :: cout << string.length();
    return 0;
}
int main ()
{
    /* in another function */
    char *badQstring = (char*)"Booohhh";
    MyCallback( (std::string )badQstring ); 
}

它工作正常。这是否意味着Qt有一些问题w.r.t回调,这并不意味着上面提到的缺陷是在普通的c++中,或者我在错误的树上吠叫?

嗯,假设Qt希望您给他一个回调,该回调以指向QString的指针作为参数:您的c++类型定义为回调将看起来像:

typedef int (*callback_function)( QString *string);

现在,当这个回调被调用时,你永远不能确定传递的参数真的是一个QString:在c++中,这个语句是有效的,很可能会使你的回调崩溃:

int MyCallback( QString *string )
{
   if(string)
       printf("QString value: %sn", string->toAscii());
}
/* in another function */
char *badQstring = "Booohhh";
MyCallback( (QString *)badQstring ); // crash, badQstring is not a QString!

由于c++允许强制类型转换,因此您永远无法确定实际传递给回调的是什么类型。但是,这个语句对任何函数都有效,即使不是回调函数。

请以sqlite3_exec()为例。它的void*参数是一个指向"上下文对象"的指针,该对象在调用回调函数时传递给回调函数。这完全取决于用户确定这个void*指向他所期望的类型。

例如,你需要一些复杂的类作为"上下文对象"。您将该类对象的地址传递给sqlite3_exec(),并将其隐式转换为void*,然后当您的回调被调用时,您必须将其从void*强制转换回来,如果您将其强制转换为错误的类型,则没有人捕获您。

这是一个指向函数的指针,有些编译器在运行时不会检查是否存在指针指向具有不同参数的函数的情况