如何访问在 if 语句内、外部创建的指针



我正在制作一个简单的程序来玩某个战斗呼叫,具体取决于用户选择的口袋妖怪。我有一个主类(口袋妖怪类),还有两个从主类继承虚拟战斗咆哮()函数的类。这是代码

#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

最新更新