Je suis en train de créer un programme simple pour jouer un certain appel au combat en fonction d'un Pokémon choisi par l'utilisateur. J'ai une classe principale (classe Pokemon) et deux classes qui héritent d'une fonction battleRoar () virtuelle de la classe principale. C'est le code
#include <iostream> using namespace std; class Pokemon{ public: virtual void battleCall(){ } virtual ~Pokemon() {} }; class Weedle: public Pokemon{ public: Weedle(){ cout << "Weedle Weedle!" << endl; } void battleCall(){ cout << "-v- weedle" << endl; } }; class Pikachu: public Pokemon{ public: Pikachu(){ cout << "Pikaaaachu!" << endl; } void battleCall(){ cout << "pikachu!!" << endl; } }; int main(){ cout << "Please pick a pokemon." << endl; cout << "1. Weedle" << endl; cout << "2. Pikachu" << endl; int a; cin >> a; if (a == 1){ cout << "You picked a weedle!" << endl; Weedle chosenPoke; Pokemon *p1 = &chosenPoke; } else if (a == 2){ cout << "You picked a pikachu!" << endl; Pikachu chosenPoke; Pokemon *p1 = &chosenPoke; } else { cout << "Invalid choice" << endl;} cout << "Would you like to hear your pokemon's battle call?" << endl; cout << "Yes or No" << endl; string choose; cin >> choose; p1->battleCall(); //produces error: use of undeclared identifier 'p1 return 0; }
Le problème que j'ai, c'est que les pointeurs de classe principale qui pointent vers la sous-classe ne sont plus accessibles en dehors du conditionnel. Dans ce cas, je sais qu'il serait simple d'appeler le rugissement dans chaque branche du conditionnel. Cependant, j'aimerais pouvoir appeler la sous-classe qui a été créée avec un pointeur, plutôt que de créer l'appel de la fonction pour chaque variante du conditionnel.
3 Réponses :
Déclarez le pointeur avant le bloc if
et modifiez la création de l'objet que vous souhaitez renvoyer.
Pokemon *p1; if (a == 1){ cout << "You picked a weedle!" << endl; /* Weedle chosenPoke; -- don't construct the object on the stack */ p1 = new Weedle(); } ... p1->battleCall(); delete p1; ...
Cela résout le problème immédiat de l'identifiant non déclaré mais ajoute le fardeau que vous devez supprimer l'objet lorsqu'il n'est plus nécessaire - ou modifier votre code pour utiliser des pointeurs intelligents.
Lors de la suppression de l'objet, je dirais "supprimer p1;", non?
Merci beaucoup pour votre aide :) cela résout mon problème
J'ai ajouté la suppression à mon exemple
@Tony Je pense que p1
devrait être défini sur nullptr. Comme mentionné dans ma réponse.
@jalajan - Prenez note du problème mis en évidence par la réponse de Kunal Puri. Lorsque vous avez un choix non valide, le programme plantera à moins que vous ne testiez un pointeur valide; qui peut être aussi simple que de placer l'appel et de supprimer dans un bloc if (p1) {...}
.
Bien que le problème majeur soit déjà résolu, vous pourriez rencontrer un problème lors de l'application de la réponse. Le pointeur p1
n'est défini sur aucune valeur valide susceptible de provoquer une erreur de segmentation.
Vous devez faire quelque chose comme ceci:
std::unique_ptr<Pokemon> p1; if (a == 1) { cout << "You picked a weedle!" << endl; p1 = std::make_unique<Weedle>(); } else if (a == 2){ cout << "You picked a pikachu!" << endl; p1 = std::make_unique<Pikachu>();; } else { cout << "Invalid choice" << endl;} cout << "Would you like to hear your pokemon's battle call?" << endl; cout << "Yes or No" << endl; string choose; cin >> choose; // In case of invalid input, it'll work!!! if (p1 != nullptr) { p1->battleCall(); }
Merci beaucoup pour l'aide :-) J'ai décidé de l'enfermer dans un si conditionnel
@jalajan Si vous utilisez un pointeur brut, n'oubliez pas de l'initialiser avec nullptr
Vous constaterez peut-être que même si main ()
n'est pas encore une fonction compliquée, la décomposer en fonction plus petite vous permet de définir plus logiquement les variables.
par exemple
std::unique_ptr<Pokemon> create(int choice) { std::unique_ptr<Pokemon> result; if (choice == 1) { std::cout << "You picked a weedle!" << std::endl; result = std::make_unique<Weedle>(); } else if (choice == 2) { std::cout << "You picked a pikachu!" << std::endl; result = std::make_unique<Pikachu>(); } else { std::cout << "Invalid choice" << std::endl; } return result; }
exemple de travail complet:
Vous pouvez déclarer
Pokemon * p1;
avant if () maisp1 = & selectedPoke;
ne fonctionnera pas puisque vous prenez l'adresse d'unselectedPoke;
qui n'existe plus en dehors du bloc.