正确实现 class 函数数组
Properly implementing an array of class functions
我想制作一个已知大小的 class 函数数组。为此,我尝试使用 typedef,但到目前为止还没有成功。
此外,有些函数不带参数。 F(),但其他人做 ex。 G(int n),并且在 typedef 中,我不知道如何告诉它不接受某些参数(试过 void 但它说它不是一种类型),并接受其他参数。
class myClass
{
// An array of void functions
typedef void(myClass::*arrayOfFunctions)();
private:
arrayOfFunctions array[3] = { &myClass::F, &myClass::G, &myClass::H };
void F() { do stuff; }
void G(int n) { do stuff involving n; }
void H() { do stuff; }
};
我尝试过的:
我已经成功地在不涉及 classes 的 main 中创建了一个 void 函数数组,我可以在需要时调用它,所以部分问题似乎是在 class 中实现它并使用它的 class 函数。
// This works:
typedef void(*arrayOfFunctions)();
void Action1()
{
// stuff 1
}
void Action2()
{
// stuff 2
}
void Action3()
{
//stuff3
}
int main()
{
arrayOfFunctions functionArray[] = { Action1, Action2, Action3 };
// Call Action1
functionArray[0]();
return 0;
)
正如评论中提到的那样,直接是不可能的。您不能在同一个数组中存储不同类型的对象。但是,有一些方法可以实现您想要的。如何到达那里很大程度上取决于细节。最近调用函数时需要知道要传递多少个参数。
在您的示例中,一种可能性是重构为只有没有参数的方法:
class myClass {
using memFun = void(myClass::*)();
void set_n(int x) { n = x; }
private:
memFun array[3] = { &myClass::F, &myClass::G, &myClass::H };
void F() { do stuff; }
void G() { do stuff involving n; }
void H() { do stuff; }
int n;
};
我更改了别名的名称,因为它只是函数指针的类型而不是数组。 using
比 typedef
更容易阅读(它遵循更常见的 x = something
风格)。
当您调用函数 G
时,参数 n
必须来自某个地方,因此您可以在迭代数组并调用所有方法之前调用 set_n
而不是直接传递它没有参数。
不清楚您想如何使用这样的数组。如果您在编译时知道元素索引,那么您可能会使用带有模板参数推导的 std::tuple
。例如:
class my_class {
public:
template<std::size_t n, class... Args>
decltype(auto) call_fn(Args&&... args) {
constexpr auto ptrs = get_fn_pointers();
return std::invoke(std::get<n>(ptrs), this, std::forward<Args>(args)...);
}
private:
static constexpr auto get_fn_pointers() {
return std::tuple(&my_class::f, &my_class::g, &my_class::h);
}
void f() {
std::cout << "f()\n";
}
void g(int n) {
std::cout << "g(" << n << ")\n";
}
int h() {
std::cout << "h() => ";
return 9102;
}
};
int main() {
my_class c;
c.call_fn<0>(); // Output: f()
c.call_fn<1>(2019); // Output: g(2019)
std::cout << c.call_fn<2>(); // Output: h() => 9102
}
我想制作一个已知大小的 class 函数数组。为此,我尝试使用 typedef,但到目前为止还没有成功。 此外,有些函数不带参数。 F(),但其他人做 ex。 G(int n),并且在 typedef 中,我不知道如何告诉它不接受某些参数(试过 void 但它说它不是一种类型),并接受其他参数。
class myClass
{
// An array of void functions
typedef void(myClass::*arrayOfFunctions)();
private:
arrayOfFunctions array[3] = { &myClass::F, &myClass::G, &myClass::H };
void F() { do stuff; }
void G(int n) { do stuff involving n; }
void H() { do stuff; }
};
我尝试过的: 我已经成功地在不涉及 classes 的 main 中创建了一个 void 函数数组,我可以在需要时调用它,所以部分问题似乎是在 class 中实现它并使用它的 class 函数。
// This works:
typedef void(*arrayOfFunctions)();
void Action1()
{
// stuff 1
}
void Action2()
{
// stuff 2
}
void Action3()
{
//stuff3
}
int main()
{
arrayOfFunctions functionArray[] = { Action1, Action2, Action3 };
// Call Action1
functionArray[0]();
return 0;
)
正如评论中提到的那样,直接是不可能的。您不能在同一个数组中存储不同类型的对象。但是,有一些方法可以实现您想要的。如何到达那里很大程度上取决于细节。最近调用函数时需要知道要传递多少个参数。
在您的示例中,一种可能性是重构为只有没有参数的方法:
class myClass {
using memFun = void(myClass::*)();
void set_n(int x) { n = x; }
private:
memFun array[3] = { &myClass::F, &myClass::G, &myClass::H };
void F() { do stuff; }
void G() { do stuff involving n; }
void H() { do stuff; }
int n;
};
我更改了别名的名称,因为它只是函数指针的类型而不是数组。 using
比 typedef
更容易阅读(它遵循更常见的 x = something
风格)。
当您调用函数 G
时,参数 n
必须来自某个地方,因此您可以在迭代数组并调用所有方法之前调用 set_n
而不是直接传递它没有参数。
不清楚您想如何使用这样的数组。如果您在编译时知道元素索引,那么您可能会使用带有模板参数推导的 std::tuple
。例如:
class my_class {
public:
template<std::size_t n, class... Args>
decltype(auto) call_fn(Args&&... args) {
constexpr auto ptrs = get_fn_pointers();
return std::invoke(std::get<n>(ptrs), this, std::forward<Args>(args)...);
}
private:
static constexpr auto get_fn_pointers() {
return std::tuple(&my_class::f, &my_class::g, &my_class::h);
}
void f() {
std::cout << "f()\n";
}
void g(int n) {
std::cout << "g(" << n << ")\n";
}
int h() {
std::cout << "h() => ";
return 9102;
}
};
int main() {
my_class c;
c.call_fn<0>(); // Output: f()
c.call_fn<1>(2019); // Output: g(2019)
std::cout << c.call_fn<2>(); // Output: h() => 9102
}