2012-07-20 40 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()); 

凡在發佈版本,它只是用參數調用函數和調試版本中你得到的檢查了。