2

多くのメニューとサブメニューを備えたコンソール アプリケーションを c++ で作成しています。メニューを表示する方法は、do-while ループです。3 つのパラメーターを使用してメニュー ループを表示する関数を作成しました。1 つ目はメニュー内のオプションの数に関連する整数、2 つ目はメニューを表示する関数、3 つ目はユーザーが入力した選択を実行する別の関数です。 .

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;
}

表示されるエラーは「エラー C2102: '&' には左辺値が必要です」です。私はプログラミングに少し慣れていませんが、関数をパラメーターとして渡すのはこれが初めてです。コメントアウトしたコードを削除するために、この関数を作成しています。誰でも私が間違っている場所と可能な解決策を指摘できますか? そうでない場合は、各メニューに重複したコードを使用するだけです。これは、プログラミングの習慣が悪いとわかっています。

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

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

それはあなたが達成しようとしていることではありません。まず、変数ではないものに対処することはできません。したがって、次のことを行う必要があります。

  1. 「&」を削除します。
  2. displayInitialMenu と performSelectionInitialMenu の後の「()」を削除します。これは、これらの関数が呼び出され、現在のケースでは無効な戻り値が menuLoop に渡されることを意味するためです。そのため、達成しようとしていることが得られません。

あなたは次のようなことをしなければなりません:

menuLoop(3, menu.displayInitialMenu, performSelectionInitialMenu, 3); 追加のパラメーターとして 3 つを渡す必要があることに注意してください。

また、それに応じて menuLoop の署名も変更します。

于 2012-05-17T11:18:52.290 に答える
0

まず第一に、関数の名前の後に括弧を付けるとすぐに、関数自体について話していることにはなりません。つまり、無料の関数 (クラスメンバーではない関数)funcは関数のアドレスを参照しますが、その関数からfunc返さfunc()れるものは何でも参照します。

ただし、別の問題があります。非静的クラス メンバー関数をフリー関数として渡そうとしています。非静的メンバー関数には隠し引数、つまり呼び出されるオブジェクトがあるため、これは c++ では有効ではありません。理論上は、呼び出されたときに onobject.memberfuncを呼び出すデリゲートを参照できますが、C++ ではそうではありません。C++ では慣例であるように、この効果を得る方法は約 10 億通りあり、さまざまな基準で 10 億通りのトレードオフがあります。memberfuncobject

あなたにとって、最も簡単なのは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 に答える