【问题标题】:How to access a pointer made within an if statement, outside of it?如何访问在 if 语句中创建的指针,在它之外?
【发布时间】:2019-06-02 15:39:53
【问题描述】:

我正在制作一个简单的程序来根据用户选择的口袋妖怪来播放特定的战斗呼叫。我有一个主类(Pokemon 类)和两个从主类继承虚拟battleRoar() 函数的类。 这是代码

#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;
}

我遇到的问题是指向子类的主类指针在条件之外不再可访问。在这种情况下,我知道在条件的每个分支中调用 roar 会很简单。但是,我希望能够使用指针调用任何子类,而不是为条件的每个变体创建调用函数。

【问题讨论】:

  • 您可以在 if() 之前声明 Pokemon *p1;,但 p1 = &amp;chosenPoke; 不起作用,因为您正在获取一个不再存在于块外的临时地址 chosenPoke;

标签: c++ pointers conditional


【解决方案1】:

您可能会发现,尽管 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

【讨论】:

    【解决方案2】:

    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;
    ...
    

    这解决了未声明标识符的直接问题,但增加了当不再需要对象时必须删除该对象或更改代码以使用智能指针的负担。

    【讨论】:

    • 删除对象的时候,我会说“delete p1;”,对吧?
    • 非常感谢您的帮助 :) 这解决了我的问题
    • 我已将删除添加到我的示例中
    • @Tony 我认为p1 应该设置为nullptr。正如我的回答中提到的那样。
    • @jalajan - 注意 Kunal Puri 的回答强调的问题。当您选择无效时,除非您测试有效指针,否则程序将崩溃;这可以像在 if (p1) { ... } 块中调用和删除一样简单。
    【解决方案3】:

    虽然主要问题已经得到解答,但您在应用答案时可能会遇到问题。指针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();
    }
    

    【讨论】:

    • 非常感谢您的帮助 :-) 我决定将它包含在 if 条件中
    • @jalajan 如果你使用原始指针,别忘了用nullptr初始化它
    猜你喜欢
    • 2020-03-30
    • 1970-01-01
    • 2021-12-27
    • 1970-01-01
    • 2012-11-13
    • 1970-01-01
    • 2015-07-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多