Reputation: 101
I am making a simple program to play a certain battle call depending on a user picked pokemon. I have one main class (Pokemon class), and two classes which inherit a virtual battleRoar() function from the main class. This is the 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;
}
The problem I have is the main class pointers which point to the subclass are no longer accessible outside of the conditional. In this case, I know it would be simple to call on the roar in each branch of the conditional. However, I would like to be able to call on whichever subclass was made with a pointer, rather than creating calling the function for each and every variation of the conditional.
Upvotes: 1
Views: 114
Reputation: 69892
You may find that even though main()
is not yet a complicated function, breaking it down into smaller function allows you to more logically scope variables.
e.g.
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;
}
full working example:
http://coliru.stacked-crooked.com/a/8e20a47e0d5e1de5
Upvotes: 1
Reputation: 10327
Declare the pointer before the if
block and change the creation of the object you want to return.
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;
...
This solves the immediate problem of the undeclared identifier but adds the burden that you must delete the object when it is no longer required - or change your code to use smart pointers.
Upvotes: 3
Reputation: 3427
Though major problem is already answered, You might face issue while applying the answer. Pointer p1
is not set to any valid value which might give segmentation fault.
You have to do something like this:
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();
}
Upvotes: 3