使用嵌套函数数组是个好主意吗?

Is it a good idea to use nested function arrays?

本文关键字:好主意 数组 嵌套 函数      更新时间:2023-10-16

我需要一个菜单。起初我使用了可怕的 if-else 级联,它看起来像这样(不要想知道奇怪的while(selection > x)循环,这只是一种奇怪的输入方式(:

int main() {
...
do {
std::cout << "nMENUn";
std::cout << "The container is " << (list.empty() ? "empty.n" : "not empty.n");
std::cout << "Enter:n1 to edit the containern2 to execute functions on itn0 to stop programn";
while((selection = intInput()) > 2)
std::cout << "Invalid input, try again.n";
if(selection == 1) {
std::cout << "nEnter:n1 to print containern2 to empty containern";
std::cout << "3 to add elements from filen4 to add elements from consolen0 to return to menun";
while((selection = intInput()) > 4)
std::cout << "Invalid input, try again.n";
if(selection == 1) {
...
}
else if(selection == 2) {
list.clear();
if(list.empty()) std::cout << "Successfully erased container.n";
}
else if(selection == 3) {
fileInput(list);
std::cout << "Successfully added elements from file.n";
}
else if(selection == 4) {
consoleInput(list);
std::cout << "Successfully added elements from console.n";
}
}
else if(selection == 2) {
std::cout << "nFUNCTION LISTn";
std::cout << "1. Find students with average mark more than K.n";
std::cout << "2. Find students with highest average mark per group (could be several).n";
std::cout << "3. Sort students by groups.n";
std::cout << "Enter function number:n";
while((selection = intInput()) > 3)
std::cout << "Invalid input, try again.n";
std::cout << "nEnter:n1 to print result in filen2 to print in console onlyn0 to return to menun";
while((selectionFile = intInput()) > 2)
std::cout << "Invalid input, try again.n";
std::cout << std::endl;
if(selectionFile == 1)
fileOutput(fileO);
if(selection == 1) {
...
std::cout << "nSuccessfully finished.n";
}
else if(selection == 2) {
...
std::cout << "nSuccessfully finished.n";
}
else if(selection == 3) {
...
std::cout << "nSuccessfully finished.n";
}
}
if(selection == 0) {
std::cout << "nEnter:n1 to return to menun0 to stop programn";
while((selection = intInput()) > 1)
std::cout << "Invalid input, try again.n";
}
} while (selection != 0);
return 0;
}

但这几乎不可读。然后有人向我提出了一个通过数组的想法,因为我所有的输入都是从 0 到 n 的整数。我将其理解为函数数组。现在它看起来像这样(只是创建数组(:

std::array <std::function < void(std::vector <std::string>) >, 2> ChoiceMain = {Edit, Func};
std::array <std::function < void(std::vector <std::string>) >, 4> ChoiceEdit1 = {Print, AddFromFile, AddFromConsole, Empty};
std::array <std::function < void(std::vector <std::string>) >, 2> ChoicePrint11 = {PrintConsole, PrintFile};
std::array <std::function < void(std::vector <std::string>) >, 3> ChoiceFunc2 = {Func1, Func2, Func3};

这是,嗯...仍然勉强可读。它应该是这样工作的:我们有桥接函数,它只是为用户打印信息,从相应的数组中获取变量并调用函数,就像我们调用函数 Edit,它需要i并调用ChoiceEdit[i];我们有做事情的最终功能。 这是创建菜单的正确方法吗?

添加几个有意义的名称

using MenuFunction = std::function<void(std::vector<std::string>)>;
template<int Items>
using Menu = std::array<MenuFunction, Items>;

你得到

Menu<2> ChoiceMain = {Edit, Func};
Menu<4> ChoiceEdit1 = {Print, AddFromFile, AddFromConsole, Empty};
Menu<2> ChoicePrint11 = {PrintConsole, PrintFile};
Menu<3> ChoiceFunc2 = {Func1, Func2, Func3};

这远非不可编辑。

一个选项是创建一个指向使用 std::map 的方法的指针:

要执行的元素(或 FSM 中的操作(:

typedef enum {
ACTION1,
ACTION2,
ACTION3
} action_t;

方法的声明:

action_t Foo::bar()

别名:

typedef action_t (Foo::*actionsPtr_t)(void);
typedef std::map<action_t, actionsPtr_t> stateFuncMap_t;

映射:

stateFuncMap_t mapping;
mapping[ACTION1] = &Foo::bar;
mapping[ACTION2] = &Foo::bar2;
mapping[ACTION3] = &Foo::bar3;

执行方式:


Foo fsm;
action_t nextAction;
nextAction = (fsm.*(mapping[ACTION1]))();
nextAction = (fsm.*(mapping[nextAction]))();

其中每个方法返回下一个要执行的方法。