2

我正在用 C++ 创建一个带有很多菜单和子菜单的控制台应用程序。我显示菜单的方式是通过 do-while 循环。我创建了一个函数来显示具有三个参数的菜单循环 - 第一个是与菜单中有多少选项有关的整数,第二个是显示菜单的函数,第三个是执行用户输入的选择的另一个函数.

class Menu {
public:

void displayInitialMenu(){
        system("cls");
    string menu = "\n\t\tXXXXXXXXX"\
      "\n\n Please select from the following:"\
      "\n\n 1. XXXXXXX"\
      "\n\n 2. XXXXXXX"\
      "\n\n 3. Exit\n";
    cout << menu << endl;
}



static bool checkOption (int option, int lower, int upper){
if ((option < lower) || (option > upper)){
    return false;   
} else {
    return true;
}
}

static int readOption(int lower, int upper){

    int option = 0;
    bool validMenuOption = false;

    do{
        std::cin >> option;
        validMenuOption = checkOption(option, lower, upper);

        if (!validMenuOption){
            std::cout << "\nError: Input must be between " << lower;
            std::cout << " and " << upper << "\n" << std::endl;     
        }
    } while (!validMenuOption);

    return option;
}
};

Menu menu;

void menuLoop(int numberOfOptions, void (*displayMenu)(), void (*switchStatement)()){
int menuOption = numberOfOptions;
do {
    (*displayMenu)();
    menuOption = menu.readOption(1, numberOfOptions);
    (*switchStatement)();
} while (menuOption != numberOfOptions);
}

static void performSelectionInitialMenu(int option){

switch (option){
case 1:
    break;

case 2:
    break;

case 3:
    break;

default:
    break;
}
}

int main()
{
/*
int menuOption = 3;
do {
    menu.displayInitialMenu();
    menuOption = menu.readOption(1, 3);
    performSelectionInitialMenu(menuOption);
} while (menuOption != 3);
*/

menuLoop(3, &menu.displayInitialMenu(), &performSelectionInitialMenu(3));

return 0;
}

我收到的错误是"error C2102: '&' requires l-value"。我对编程有点陌生,这是我第一次将函数作为参数传递。我正在制作这个函数来消除我已经注释掉的代码。任何人都可以指出我出错的地方和可能的解决方案。如果没有,我会为每个我知道是不好的编程习惯的菜单使用重复的代码。

4

4 回答 4

2

您正在尝试获取由函数displayInitialMenu和返回的值的地址performSelectionInitialMenu,但这两个函数均不返回任何内容 ( void)。删除&两个调用前面的 以解决此特定问题。

于 2012-05-17T10:19:33.853 回答
2

通常你只会这样称呼它:

menuLoop(3, menu.displayInitialMenu, performSelectionInitialMenu);

只是名称,没有参数。

然而,performSelectionInitialMenu是:

static void performSelectionInitialMenu(int option)

所以它与指针的签名不匹配:

void (*switchStatement)()

这意味着它们不兼容。

于 2012-05-17T10:23:07.140 回答
0

首先,只要你把括号放在函数名之后,你就不再是在谈论函数本身了。即对于自由函数(不是类成员的函数)func指的是函数的地址func,而func()指的是从该函数返回的任何内容。

你还有另一个问题。您正在尝试将非静态类成员函数作为自由函数传递。这在 c++ 中是不合法的,因为非静态成员函数有一个隐藏参数,即调用它的对象。尽管理论上object.memberfunc可以引用一个在调用时调用memberfuncon的委托object,但它在 C++ 中没有。按照 C++ 的惯例,大约有 10 亿种方法可以获得这种效果,并在各种标准中进行了 10 亿次权衡。

我认为,对你来说,最简单的是使用boost.bind。所以,你想要做的看起来像:

#include<boost/bind.hpp>
using namespace boost;

...

template <class Functional>
void menuLoop(int numberOfOptions, Funcional displayMenu, void (*switchStatement)()){

...

menuLoop(3, bind(Menu::displayInitialMenu,menu), &performSelectionInitialMenu(3));

...
于 2012-05-17T10:34:58.753 回答
0

menuLoop(3, &menu.displayInitialMenu(), &performSelectionInitialMenu(3));

这不是你想要达到的目标。首先,您不能处理不变的事物。因此,您必须执行以下操作:

  1. 去除那个 ”&”。
  2. 删除 displayInitialMenu 和 performSelectionInitialMenu 之后的“()”,因为这确实意味着将调用这些函数,并且在当前情况下为 void 的返回值将传递给 menuLoop。所以,你不会得到你想要达到的目标。

您必须执行以下操作:

menuLoop(3, menu.displayInitialMenu, performSelectionInitialMenu, 3); 请注意,您必须将三个作为额外参数传递。

并相应地更改 menuLoop 的签名。

于 2012-05-17T11:18:52.290 回答