函数指针数组:void** cast

function pointer array: void** cast

我对 C 和 C++ 比较陌生。我有任务(更多的是练习)将给定的 c 模块更改为 c++。为此,我必须先了解c文件。

我有两个具体问题,但我想简要概述一下函数的各个部分。我尝试使用通用标识符。

c代码摘录:

有一个 Broker 提供注册回调函数。 Broker 在各自的数组中保存不同类型的回调。

首先,他们声明了几个函数指针来指定回调:

typedef bool (*ReadRequestCallback_tpf)  (param1 a, param2 b, param3 c);
typedef bool (*ReadResponseCallback_tpf) (param4 a, param5 b);
typedef bool (*WriteRequestCallback_tpf) (param6 a, param7 b, param8 c);
...

然后,他们为每种类型制作了数组来保存注册的回调:

ReadRequestCallback_tpf  ReadRequest_apf  [MaxReadRequest];
ReadResponseCallback_tpf ReadResponse_apf [MaxReadResponse];
WriteRequestCallback_tpf WriteRequest_apf [MaxWriteRequest];

提供了注册新回调函数:

void RegisterReadRequestCallback_v (ReadRequestCallback_tpf callback_pf){
    AddCallback_v((void**)ReadRequest_apf, (void*) callback_pf);
}
void RegisterReadResponseCallback_v (ReadResponseCallback_tpf callback_pf){
    AddCallback_v((void**)ReadResponse_apf, (void*) callback_pf);
}
void RegisterWriteRequestCallback_v (WriteRequestCallback_tpf callback_pf){
    AddCallback_v((void**)WriteRequest_apf, (void*) callback_pf);
}

AddCallback_v的签名是这样的:

void AddCallback_v (void* Array_apv[], void* function_pf)

我的问题:

  1. (void**) array_apf真的void* array_apv吗? 所以 'array of function pointers' 到 'void-pointer to void-pointer' 的转换等于 'void-pointer to an array of void-pointer'? 因为它有效,所以看起来是这样。但我真的不明白。

  2. 当尝试将它(或部分)更改为 c++ 时,使用模板而不是强制转换为 (void*) 是否更好?

这是我在这里的第一个条目。我希望,我可以解释我的问题。如果有什么需要澄清的,请告诉我。

谨致问候并提前致谢

  1. 当数组传递给函数时,它会自动转换为指向第一个元素的指针。所以在函数声明中,TYPE array[] 等同于 TYPE *array。因此,void *array[] 等价于 void **array.

  2. 模板的目的之一是避免必须将 void * 类型用于泛型函数,因为编译器无法确保您将其转换回使用指针时的原始类型。所以是的,模板通常是比采用 void* 参数的函数更好的解决方案。

C 代码实际上已损坏。 指向任何对象的任何指针都可以转换指向void的指针,但事实并非如此指向函数的指针。此外,不能保证指向函数的指针可以 reinterpreted 作为 C 中的 pointer-to-void。这意味着函数

void RegisterReadRequestCallback_v (ReadRequestCallback_tpf callback_pf){
    AddCallback_v((void**)ReadRequest_apf, (void*) callback_pf);
}

在很多方面都被破坏了,包括它破坏了严格的别名。错得让人心疼

这样做的目的显然是有一个名为 AddCallback_v 的通用函数获取指向回调数组的指针,以及一个新的回调函数,但是 C 不保证它会像那样工作!

在 C 中,编写此代码的正确方法是让 Readrequest_apf 等成为通用 函数指针 的数组;在调用它们之前将被转换回 ReadRequestCallback_tpf 等人,即

typedef bool (*GenericCallback_tpf)();

GenericCallback_tpf ReadRequest_apf[MaxReadRequest];

void AddCallback_v(GenericCallback_tpf callback_array[]);

void RegisterReadRequestCallback_v (ReadRequestCallback_tpf callback_pf){
    AddCallback_v(ReadRequest_apf, (GenericCallback_tpf)callback_pf);
}

调用时:

((ReadRequestCallback_tpf)ReadRequest_apf[i])(param1, param2, param3);

在 C++ 中,您将为每个 *_apf 使用一个 函子向量 ;因此不需要强制转换。