2012-07-20 49 views
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(如上面的代码)。但是这种解决方案可能会导致不安全的函数调用,因为在编译期间无法检查数据类型。 当参数的类型与参数不同时,是否有一些方法让编译器报告错误?如何让编译器检查数据,而不C++ 11

事情是这样的:

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 
.... 
} 

我对此非常感谢。

+2

真实类型是什么意思?不,您无法安全地从void中找到“该类型”* – 2012-07-20 18:35:54

+0

即使参数类型DO匹配,此行PF PF =(PF)(void *)&f;也被破坏(与实现有关,不可移植)。见5.2.10p8。 – 2012-07-20 19:27:54

回答

1

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

真的,你应该只是避免强制转换函数指针。函数指针的唯一位置是必需的是来自GetProcAddressdlsym的返回值。

0

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

0

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

它怎么知道?你被破坏类型系统(这是什么投到void* s做)。你告诉C++编译器假装一个函数指针是一个指向任何东西的指针,然后你告诉它假装这个指向任何东西的指针是指向一个不同类型函数的指针。

编译器无法知道原始类型是什么。它只知道有一个void*,你要求将它转换成某种东西。为了允许void*工作,C++语言不要求编译器神奇地知道void*来自哪里以及它曾经是什么。因此,你可以将它投射到任何东西上,但是规范说明如果你将它投到不是原始类型,你会得到未定义的行为。

C++中的类型系统允许编译器检测你什么时候做错了什么。通过颠覆它,然后做错了,你已经放弃了生活在理性世界中的所有权利。你告诉编译器,“我知道我在做什么”,然后在脚下开枪。

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

+1

函数指针不能绕过'void *'。那不会打破Boost.Any? – 2012-07-20 19:24:21

+0

在检查源代码时,似乎应该可以......但是有很多关于Boost.Any将东西存储为“void *”的错误信息。 – 2012-07-20 19:26:59

0

根据不同品种你有函数类型的,你添加了一些测试或调试版本:

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

... 

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

我敢肯定,有些升压和/或C++ 11的魔法,你可以删除需要有一个“KIND”,并从原始函数类型中隐式推导出它。你很可能最终与您的通话寻找如下:

CHECKED_CALL (pf, 10, string()); 

凡在发布版本,它只是用参数调用函数和调试版本中你得到的检查了。