1
votes

Comment accéder à un pointeur fait dans une instruction if, en dehors de celle-ci?

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.


1 commentaires

Vous pouvez déclarer Pokemon * p1; avant if () mais p1 = & selectedPoke; ne fonctionnera pas puisque vous prenez l'adresse d'un selectedPoke; qui n'existe plus en dehors du bloc.


3 Réponses :


3
votes

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.


5 commentaires

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) {...} .



3
votes

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


2 commentaires

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



1
votes

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:

http: //coliru.stacked-crooked.com/a/8e20a47e0d5e1de5


0 commentaires