2012-05-17 4 views
2

Je crée une application console en C++ avec beaucoup de menus et de sous-menus. La façon dont j'affiche mon menu est à travers une boucle do-while. J'ai créé une fonction pour afficher la boucle de menu avec trois paramètres - d'abord un entier qui concerne le nombre d'options dans le menu, le second étant une fonction affichant le menu et le troisième étant une autre fonction qui effectue la sélection entrée par l'utilisateur .C++ Erreur C2102: '&' nécessite une valeur l

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

L'erreur que je reçois est "C2102 d'erreur: '&' exige l valeur". Je suis un peu novice en programmation et c'est la première fois que je passe une fonction en paramètre. Je fais cette fonction pour éliminer le code que j'ai commenté. Quelqu'un peut-il pointer vers où je vais mal et une solution possible. Si ce n'est pas le cas, j'utiliserai simplement du code en double pour chaque menu qui, je le sais, est une mauvaise pratique de programmation.

+1

Veuillez poster ** code ** minimum. La première étape en posant une question en ligne est de condenser le code à un minimum absolu qui présente toujours le problème. Cela fait partie de vos devoirs et rend notre tâche beaucoup plus facile. –

+0

En outre, lors de la publication des messages d'erreur, veuillez publier le message d'erreur complet, y compris le numéro de ligne où il s'est produit. – irobot

Répondre

2

Vous essayez de prendre les adresses de valeurs, retournées par les fonctions displayInitialMenu et performSelectionInitialMenu, mais ces deux fonctions ne retournent rien (void). Supprimer le & devant les deux appels pour résoudre ce problème particulier.

+0

J'ai enlevé le & mais maintenant je reçois une nouvelle erreur. C2664: 'menuLoop': impossible de convertir le paramètre 2 de 'void' en 'void (_cdecl *) (void)' – Indy411

+0

Non, vous avez besoin de '&' pour transmettre l'adresse de la fonction. Gardez-le, mais supprimez les parenthèses et corrigez les signatures de fonction respectives. – irobot

+0

Merci, tout fonctionne maintenant. Appréciez l'aide les gars – Indy411

2

Normalement, vous ne l'appeler comme ceci:

menuLoop(3, menu.displayInitialMenu, performSelectionInitialMenu); 

ne citer que, aucun paramètre.

Cependant, performSelectionInitialMenu est:

static void performSelectionInitialMenu(int option) 

Il ne correspond pas à la signature du pointeur:

void (*switchStatement)() 

ce qui signifie qu'ils ne sont pas compatibles.

+0

N'a pas vu celui-là. Bonne prise! – irobot

+0

Vous devrez également rendre Menu :: displayInitialMenu statique. – acraig5075

+0

Merci, j'aurais couru dans cette erreur suivante – Indy411

0

Tout d'abord, dès que vous mettez les parenthèses après le nom d'une fonction, vous ne parlez plus de la fonction elle-même. i.e pour les fonctions libres (fonctions qui ne sont pas membres de la classe) func fait référence à l'adresse de la fonction func, alors que func() fait référence à ce qui est renvoyé par cette fonction.

Vous avez cependant un autre problème. Vous essayez de transmettre une fonction de membre de classe non statique en tant que fonction gratuite. Ce n'est pas légal en C++, puisque les fonctions membres non statiques ont un argument caché, à savoir, l'objet sur lequel il est appelé. Bien qu'en théorie object.memberfunc pourrait se référer à un délégué qui, lorsqu'il est appelé, appelle memberfunc sur object, il ne le fait pas en C++. Comme d'habitude en C++, il y a environ un milliard de façons d'obtenir cet effet avec un milliard de compromis selon divers critères.

Je pense, pour vous, le plus simple est d'utiliser boost.bind. Donc, ce que vous essayez de faire ressemblerait à ceci:

#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)); 

... 
0

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

Ce n'est pas ce que vous essayez d'atteindre. Tout d'abord, vous ne pouvez pas prendre l'adresse des choses, qui ne sont pas variables.Donc, vous devrez faire ce qui suit:

  1. supprimer le "&". Supprimer le "()", après displayInitialMenu et performSelectionInitialMenu, car cela signifie que ces fonctions seront appelées et la valeur de retour qui est vide dans le cas actuel, sera passée à menuLoop. Donc, vous n'obtiendrez pas ce que vous essayez d'atteindre.

que vous devez faire quelque chose comme:

menuLoop (3, menu.displayInitialMenu, performSelectionInitialMenu, 3); Veuillez noter que vous devrez passer trois comme paramètre supplémentaire.

et également de modifier la signature de menuLoop en conséquence.

Questions connexes