对返回的局部变量的引用

Reference to local variable returned

我正在尝试为一个基于文本的游戏实现一个角色选择方法,我知道它不会像我那样工作,因为我return引用了一个object 的生命周期仅限于方法调用的范围。我还尝试在不参考 Fighter parent class 和 returning a child class(Samus 和 Ryu)的情况下根据玩家角色实现该方法选择,但随后我会收到此错误:无效的抽象 return 类型 'Fighter'.

Fighter characterSelection(int player,bool checkForBot, Fighter &fig)
{
int input;
string newName;

if(checkForBot)
{
    input = (rand()%2)+1;
}
else{
    cout << "Please choose your Fighter player"<<player<<": \n1. Samus\n2. Ryu\n";
    input = readInput<int>();
}
if(input == 1)
{
    Samus sam;
    if(checkForBot)
    {
        cout << "Bot selected Samus!";
    }
    else{
        cout << "Player"<<player<<" selected Samus!\nDo you wish to change your fighters name?\n1.Yes\n2.No\n";
        input = readInput<int>();
        if(input == 1)
        {
            cout << "new Name: ";
            newName = readInput<string>();
            changeName(newName,sam);
        }
    }
    return sam;
}
else if(input == 2)
{
    Ryu ry;
    if(checkForBot)
    {
        cout << "Bot selected Ryu!";
    }
    else {
        cout << "Player"<<player<<" selected Ryu!\nDo you wish to change your fighters name?\n1.Yes\n2.No\n";
        input = readInput<int>();
        if(input == 1)
        {
            cout << "new Name: ";
            newName = readInput<string>();
            changeName(newName,ry);
        }
    }
    return ry;
 }
}

选择一个字符并结束函数调用后,调用 object 的析构函数,从而使引用链接到 non-existing object。

int main()
{
int input;
string newName;
bool checkForBot;
int player=1;
while(true)
{
    cout << "1. PVP \n2. PVE\n";
    input = readInput<int>();
    if(input == 1)
    {
       checkForBot = false;
        //Character Selection
        Fighter &fig1 = characterSelection(player,checkForBot,fig1);
        player++;
        Fighter &fig2 = characterSelection(player,checkForBot,fig2);
        //Battle
        fightPVP(fig1, fig2);

    }
    else if(input ==2)
    {
        //Character Selection
        Fighter &fig1 = characterSelection(player,checkForBot,fig1);
        checkForBot = true;
        Fighter &bot = characterSelection(player,checkForBot,bot);
        //Battle
        fightPVE(fig1, bot);
    }
}
return 0;
}

有没有其他方法可以解决这个问题,而不是引用 parent class 然后在函数调用中创建 child?

在此:

Fighter &fig1 = characterSelection(player,checkForBot,fig1);

您正在引用由函数 return 编辑的本地对象副本。

返回父对象也有对象的问题slicing;你应该考虑到这一点。

但是,如果这不是问题,您可以向 class 添加一个复制构造函数,并在声明接收变量时删除引用:

Fighter fig1 = characterSelection(player,checkForBot,fig1);

如果您的对象不适合复制,另一种方法是 new characterSelection 和 return 中的对象 return 基 class.

对于您的代码,编译器是正确的。从函数 'characterSelection' 你 return 抽象 class 战斗机的实例是错误的,因为抽象 classes 不能实例化。您只能 return 指向抽象 class 的指针或引用(Fighter* 或 Figther&)(指针通常是首选方式)。据我所知,使用继承形式实现抽象 class 并在运行时选择一种战斗机的唯一方法是:

#include <iostream>

class Fighter
{
    public:
        virtual void f() = 0;
        virtual ~Fighter() {};
};

class Samus : public Fighter
{
    public:
        void f() { std:: cout << "Samus\n"; }
};

class Ryu : public Fighter
{
    public:
        void f() { std:: cout << "Ryu\n"; }
};

Fighter* getFigther()
{
    int fighterCode;

    std::cin >> fighterCode;
    switch (fighterCode)
    {
        case 0: return new Samus();
        case 1: return new Ryu();
        default: return nullptr;
    }
}

int main()
{
    Fighter* myF = getFigther();
    
    // Do what you want with the fighter
    myF->f();

    // Release the resources
    delete myF;
}

如果你出于任何原因想避免堆分配,你可以使用新的放置语法来做到这一点:

#include <iostream>

class Fighter
{
    public:
        virtual void f() = 0;
        virtual ~Fighter() {};
};

class Samus : public Fighter
{
    public:
        void f() { std:: cout << "Samus\n"; }
};

class Ryu : public Fighter
{
    public:
        void f() { std:: cout << "Ryu\n"; }
};

constexpr std::size_t size()
{
    constexpr std::size_t samusS = sizeof(Samus);
    constexpr std::size_t ryuS = sizeof(Ryu);

    return samusS < ryuS ? ryuS : samusS;
}

void getFigther(Fighter*& f)
{
    int fighterCode;

    std::cin >> fighterCode;

    // If figtherCode is invaild you can print a message or throw an exception
    switch (fighterCode)
    {
        case 0: new (f) Samus(); break;
        case 1: new (f) Ryu(); break;
    }
}

int main()
{
    char space[size()];
    Fighter* myF = (Fighter*) (space);
    getFigther(myF);
    
    // Do what you want with the fighter
    // No delete requied
    myF->f();
}

但是,如果您有多个大小不同的战士 class,您将需要一个编译时函数来为您提供任何 class(代表一个战士)的最大大小。我认为这种方法不值得你付出努力。