对返回的局部变量的引用
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(代表一个战士)的最大大小。我认为这种方法不值得你付出努力。
我正在尝试为一个基于文本的游戏实现一个角色选择方法,我知道它不会像我那样工作,因为我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(代表一个战士)的最大大小。我认为这种方法不值得你付出努力。