[英]Converting between function pointer types
我有一個程序,必須將函數存儲為void (*) (void*)
。 使用該簽名創建函數會導致代碼重復(通常第一行是將void指針強制轉換為正確的類型)並減少類型安全性(void指針可以轉換為任何內容,例如錯誤的類型),所以我想知道如果我可以使用void (*)(T*)
類型的函數,然后將其轉換為void(*)(void*)
並像這樣調用它,方式類似於:
#include <iostream>
#include <string>
void printer(std::string* string)
{
std::cout << *string << std::endl;
}
int main()
{
//Cast the function to a one that takes a void pointer
auto func = reinterpret_cast<void(*)(void*)>(&printer);
//Create a string and call the function with it
std::string string = "Hello World";
func(&string);
return 0;
}
上面的代碼編譯並運行良好(在ideone上 ),但我想知道它是否符合所有標准,或者它是否是未定義的行為,並且只是對我的具體示例和操作系統正常工作
這是未定義的行為。
[expr.call] / 1:
通過函數類型與被調用函數定義的函數類型不同的表達式調用函數會導致未定義的行為。
[expr.reinterpret.cast] / 6:
函數指針可以顯式轉換為不同類型的函數指針。 除了將“指向
T1
指針”的prvalue轉換為“指向T2
指針”類型(其中T1
和T2
是函數類型)並返回其原始類型產生原始指針值之外,這種指針轉換的結果未指定。
C ++根本不允許很多函數轉換工作,即使是你可能認為安全的事情就像更改const
細節一樣。 當您需要這樣的東西時,請使用顯式的包裝函數。 非捕獲lambda可以是一種簡單的方法來編寫一個而不命名它; 或者您可以定義一個通用模板,以您需要的方式包裝其他功能。
[奇怪的是,C ++ 17允許從指針到非投擲函數的隱式轉換到指向潛在拋出函數的指針,即使C ++ 17生成那些不同的函數類型 - 但是后來沒有任何措辭我可以看到你說'允許通過轉換后的指針實際調用該函數。
這樣做的行為是不確定的。 標准(草案)說:
[expr.reinterpret.cast]函數指針可以顯式轉換為不同類型的函數指針。 [注意:通過指向函數類型(9.2.3.5)的指針調用函數的效果與函數定義中使用的類型不同是未定義的。 - 結束注釋除了將“指向T1的指針”類型的prvalue轉換為“指向T2的指針”類型(其中T1和T2是函數類型)並返回其原始類型產生原始指針值,這樣的結果指針轉換未指定。 [注意:有關指針轉換的更多詳細信息,請參見7.3.11。 - 結束說明]
你可以使用lambda:
void(*func)(void*) = [](void *string) {
printer(static_cast<std::string*>(string));
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.