![](/img/trans.png)
[英]function pointer for different functions with different data types or parameter
[英]A function that returns a function pointer for functions of different return types
這個問題的背景圍繞着硬類型遺傳編程。
我想從函數返回一個函數指針,但這些函數指針指向具有不同返回類型的函數。 在另一個堆棧溢出問題( 具有不同返回類型 C 的函數指針)中,建議使用聯合的返回類型,但是我正在努力實現。
我對 C++ 相當陌生,所以如果它顯示出來,請原諒我的無知。
#include <iostream>
#include <string>
float Add(float a, float b) { return a + b; }
bool IfElse(bool a) { if (a) { return true; } else { return false; }; }
union return_type
{
float(*ffptr)(float, float);
bool(*bfptr)(bool);
};
union fptr(std::string OPERATION) {
if (OPERATION == "Add") {
return_type.ffptr = Add;
} else if (OPERATION == "IfElse") {
return_type.bfptr = IfElse;
}
return return_type;
}
int main() {
std::cout << fptr("Add") << std::endl
return 0;
}
我期望(或者更確切地說是希望)這會打印函數 Add 的地址
TL;DR 版本:我認為您可能正在嘗試敲定解決方案以解決問題。 考慮使用諸如訪問者模式之類的東西來解耦問題,這樣您就不需要知道數據的類型。
union
不是一種類型。 它是一種類型,如class
或struct
。 為了使用return_type
,您必須創建一個return_type
對象。 這意味着
union fptr(std::string OPERATION) {
if (OPERATION == "Add") {
return_type.ffptr = Add;
} else if (OPERATION == "IfElse") {
return_type.bfptr = IfElse;
}
return return_type;
}
需要看起來更像
return_type fptr(std::string OPERATION) {
return_type result; // make a return_type object
if (OPERATION == "Add") {
result.ffptr = Add; // set a member of the object
} else if (OPERATION == "IfElse") {
result.bfptr = IfElse;
}
return result; // return the object
}
然后你可以
int main() {
std::cout << fptr("Add").ffptr(10,20) << std::endl; // call the stored function
return 0;
}
union
的一個大問題是知道它們里面有什么。 如果ffptr
是最后一個成員集,您只能安全地使用ffptr
。
int main() {
std::cout << fptr("Add").bfptr(true) << std::endl;
return 0;
}
將編譯,但在運行時根本不會表現良好。 會發生什么是不確定的,但很有可能它不會很漂亮。
您必須絕對確定存儲在聯合中的函數是正確的。 如果您的編譯器是最新的,您可以使用std::variant
來提供幫助。 它至少會通過拋出異常告訴你你正朝着錯誤的方向前進
#include <iostream>
#include <string>
#include <variant>
float Add(float a, float b) { return a + b; }
bool IfElse(bool a) { if (a) { return true; } else { return false; }; }
using return_type = std::variant<float (*)(float a, float b), bool (*)(bool a)>;
return_type fptr(std::string OPERATION) {
return_type result;
if (OPERATION == "Add") {
result = Add;
} else if (OPERATION == "IfElse") {
result = IfElse;
}
return result;
}
int main() {
std::cout << std::get<float (*)(float a, float b)>(fptr("Add"))(10,20) << std::endl;
try
{
std::cout << std::get<bool (*)(bool a)>(fptr("Add"))(true) << std::endl;
}
catch (const std::bad_variant_access& e)
{
std::cout << e.what() << std::endl;
}
return 0;
}
但在一天結束時,它仍然不是那么有用。 我認為您可能會發現訪問者模式或其一位朋友更有幫助。
你很接近。 注意不要混淆(聯合)類型名稱的聲明和函數返回值。 由於您要引用指針地址,因此我在您的聯合 (fpaddr) 中添加了一個 void*,因此您可以清楚地識別出您正在打印一個地址。 請注意,您的 fptr("Add") 返回了聯合,並且您需要消除您想要的聯合的哪種解釋的歧義。
#include <iostream>
#include <string>
float Add(float a, float b) { return a + b; }
bool IfElse(bool a) { if (a) { return true; } else { return false; }; }
//typedef //in C you would use 'typedef'
union fp_return_t
{
float(* ffptr )(float, float);
bool(* bfptr )(bool);
void* fpaddr;
}; //fp_return_t; //in C you would give the name here
fp_return_t fptr(std::string OPERATION) {
fp_return_t fp_return;
if (OPERATION == "Add") {
std::cout << "Add:" << (void*) Add << std::endl;
fp_return.ffptr = Add;
} else if (OPERATION == "IfElse") {
std::cout << "IfElse:" << (void*) IfElse << std::endl;
fp_return.bfptr = IfElse;
}
return fp_return;
}
int main() {
std::cout << fptr("Add").fpaddr << std::endl;
return 0;
}
我不太確定最終目標是什么,但這里是如何使上述編譯並打印函數地址(打印Add
的普通Add
以進行比較):
#include <iostream>
#include <string>
float Add(float a, float b) { return a + b; }
bool IfElse(bool a) { return a; }
union return_type
{
float(*ffptr)(float, float);
bool(*bfptr)(bool);
};
union return_type fptr(std::string OPERATION) {
union return_type r;
if (OPERATION == "Add") {
r.ffptr = Add;
} else if (OPERATION == "IfElse") {
r.bfptr = IfElse;
}
return r;
}
int main()
{
/*the void*-cast is technically nonportable but it's hard to
print fn-pointers portably*/
std::cout << reinterpret_cast<void*>(Add) << '\n';
/*you should know which union member is active: */
std::cout << reinterpret_cast<void*>(fptr("Add").ffptr) << '\n';
/*^should be the same address*/
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.