请参阅此GTK回调函数:
static gboolean callback(GtkWidget *widget, GdkEventButton *event, gpointer *data)
{
AnyClass *obj = (AnyClass*) data;
// using obj works
}
(请注意数据上的gpointer *)。然后使用以下信号连接信号:
AnyClass *obj2 = new AnyClass();
gtk_signal_connect(/*GTK params (...)*/, callback, obj2);
看到* AnyClass将被转换为gpointer *(void **)。事实上,这现在正在发挥作用。 GTK文档中的回调原型是“gpointer数据”,而不是代码中显示的“gpointer * data”,我想知道的是:它如何工作?这样安全吗?
答案 0 :(得分:2)
这并不完全安全,特别是因为在使用c风格的演员表时,你已经从执行从T1 *到void *的static_cast,再到从T1 *到void **的reinterpret_cast。但是,它的工作原理是因为标准保证你可以从T1 *到T2 *(在这种情况下T2 = void *)重新解释,然后再返回以获得你开始时的相同T1 * .... T1 *的IFF对齐要求T2 *是相同的。
换句话说,它适用于大多数实现。来自void *的演员阵容是有保证的,但我不知道对于void **有任何要求。
进行reinterpret_cast总是有点风险。你必须在两侧完全正确地使用T1,如果你弄错了,编译器无法帮助你。例如,如果你从类T5(它是T1的子类)转换,然后在另一侧转换为T1 * ...你可能完全搞砸了。我认为static_cast会解释这个,但是reinterpret_cast不会。它可以正常工作,直到有人因为某种原因在T5上使用多重继承。
通过在隐藏类型中添加*,您无法获得任何收益。你应该考虑不这样做。
注意:我的答案是关于C ++语言。你把你的问题标记为两者,这样你就可以得到两者的答案,而且它们将会非常不同。
答案 1 :(得分:1)
指针本质上是一个数字。指向指针的指针也是一个数字。当你使用强制转换时,你基本上抛弃了任何类型的信息/语义,只要变量大小是兼容的(并且每个指针,包括指针到指针的大小都相同)。
假设您的新AnyClass
对象已在0x12345678
分配。
AnyClass *obj2 = new AnyClass(); // obj2 = 0x12345678
然后你将它的地址传递给gtk_signal_connect(nb。你应该使用g_signal_connect
):
gtk_signal_connect (/* args */, 0x12345678);
然后,调用您的回调,并提供您提供的参数数据:
callback (address_of_widget, address_of_event_structore, 0x12345678); // because you passed 0x12345678 in gtk_signal_connect
现在,因为0x12345678
是有效地址,所以可以将其强制转换为有效的AnyClass
指针。 data
参数可以定义为gpointer************
,无关紧要,因为当您将其转换为AnyClass*
时,无论如何都会丢弃原始类型信息。