1
void f(string str,int i )
{
  cout<<str.c_str()<<endl;
  cout<<i<<endl;
}

typedef void (*PF)(int i,string str);


int _tmain(int argc, _TCHAR* argv[])
{

   PF pf=(PF)(void*)&f;

   pf(10,string()); //runtime-error

   return 0;

}

由于某些需要,我需要使用已擦除数据类型f的地址来调用函数(如上面的代码)。f但是这种解决方案可能会导致不安全的函数调用,因为在编译过程中无法检查数据类型。当参数类型与参数不同时,是否有一些方法可以让编译器报告错误?

是这样的:</p>

void f(T1 i,T2 j)
{
  T1 p* = new i.real_type; //if i.real_type is different from T1, it will lead a compiling 
....
}

我非常感谢。

4

4 回答 4

1

C++ 中唯一可用的运行时类型信息是typeidand dynamic_cast,它们仅适用于多态类型(具有虚函数的类类型)。函数指针不存储必要的信息。

真的,你应该避免强制转换函数指针。唯一需要函数指针大小写的地方是orGetProcAddress的返回值dlsym

于 2012-07-20T18:43:06.467 回答
0

不,没有安全的方法可以从 void* 中“获取类型”。可能有一种干净的方法可以解决您的实际问题,因此不需要 void* 。我建议你在那里发布一个新问题,解释你的具体任务。

于 2012-07-20T18:49:54.010 回答
0

当参数类型与参数不同时,是否有一些方法可以让编译器报告错误。

它怎么会知道?您颠覆了类型系统(这就是强制转换为void*s 所做的事情)。你告诉 C++ 编译器假装一个函数指针是一个指向任何东西的指针,然后你告诉它假装这个指向任何东西的指针是一个指向不同类型函数的指针。

编译器无法知道原始类型是什么。它只知道有一个void*,并且您要求将其转换为某种东西。为了完全允许void*工作,C++ 语言不需要编译器神奇地知道 avoid*来自哪里以及它曾经是什么。因此,您可以将其转换为任何类型,但规范指出,如果您将其转换为的不是原始类型,您将获得未定义的行为。

C++ 中的类型系统允许编译器检测您何时做错了什么。通过颠覆它,然后做错事,你就放弃了生活在理性宇宙中的所有权利。你告诉编译器,“我知道我在做什么”,然后朝自己的脚开枪。

您可以做的最好的事情是使用Boost.Any来存储您的函数指针。任何将其转换为除最初存储在其中的内容之外的任何内容的尝试都将引发异常。当然,在运行时

于 2012-07-20T19:02:07.237 回答
0

根据您拥有的各种功能类型,您可以添加一些用于测试或调试构建的内容:

// Once off init call
DEBUG_INSERT (&f, INT_STRING);

...

DEBUG_CHECK_FUNC (pf, INT_STRING); 
pf(10,string()); //runtime-error

我很确定,通过一些 boost 和/或 c++11 魔法,您可以消除对“KIND”的需求,并从原始函数类型中隐式推导出它。您最终可能会看到如下所示的呼叫:

CHECKED_CALL (pf, 10, string ());

在发布版本中,它只是使用参数调用函数,而在调试版本中,您也可以进行检查。

于 2012-07-20T19:20:34.653 回答