我正在制作一个简单的程序来玩某个战斗呼叫,具体取决于用户选择的口袋妖怪。我有一个主类(口袋妖怪类),还有两个从主类继承虚拟战斗咆哮()函数的类。这是代码
#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;
}
我遇到的问题是指向子类的主类指针在条件之外不再可访问。在这种情况下,我知道在条件的每个分支中调用咆哮会很简单。但是,我希望能够调用使用指针创建的任何子类,而不是为条件的每个变体创建调用函数。
在 if
块之前声明指针,并更改要返回的对象的创建。
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;
...
这解决了未声明标识符的直接问题,但增加了在不再需要对象时必须删除对象的负担 - 或者更改代码以使用智能指针。
虽然主要问题已经得到解答,但在应用答案时您可能会遇到问题。指针p1
未设置为任何可能导致分段错误的有效值。
你必须做这样的事情:
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();
}
发现,即使main()
还不是一个复杂的函数,将其分解为更小的函数可以让您更合乎逻辑地限定变量的范围。
例如
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;
}
完整的工作示例:
http://coliru.stacked-crooked.com/a/8e20a47e0d5e1de5