如何解决在 cpp 中的工厂方法的情况下,继承如何工作?
我正在尝试解决 codeames 上的这个简单谜语,我想我会在 OOP 中进行练习 但是,我似乎忘记了 CPP 在该领域的工作原理,并且出现了一个我无法理解的错误。
/tmp/Answer.cpp:82:1: error: invalid abstract return type ‘Sign’
82 | Sign from_str(const int value,const std::string& s)
| ^~~~
/tmp/Answer.cpp:14:7: note: because the following virtual functions are pure within ‘Sign’:
14 | class Sign {
| ^~~~
/tmp/Answer.cpp:22:25: note: ‘virtual std::string Sign::str() const’
22 | virtual std::string str() const = 0;
| ^~~
/tmp/Answer.cpp:82:6: error: invalid abstract return type for function ‘Sign from_str(int,const string&)’
82 | Sign from_str(const int value,const std::string& s)
| ^~~~~~~~
/tmp/Answer.cpp: In function ‘Sign from_str(int,const string&)’:
/tmp/Answer.cpp:85:26: error: cannot allocate an object of abstract type ‘Sign’
85 | return Rock(value);
| ^
/tmp/Answer.cpp:87:27: error: cannot allocate an object of abstract type ‘Sign’
87 | return Paper(value);
| ^
/tmp/Answer.cpp:89:30: error: cannot allocate an object of abstract type ‘Sign’
89 | return Scissors(value);
| ^
/tmp/Answer.cpp:91:28: error: cannot allocate an object of abstract type ‘Sign’
91 | return Lizard(value);
| ^
/tmp/Answer.cpp:93:27: error: cannot allocate an object of abstract type ‘Sign’
93 | return Spock(value);
代码如下:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class Rock;
class Paper;
class Scissors;
class Sign {
public:
Sign(const int v): value(v) {};
virtual ~Sign() {};
bool operator<(const Sign& other) { return value < other.value ? false : true; }
virtual std::string str() const = 0;
int value{};
};
class Rock : public Sign {
public:
Rock(const int v): Sign(v) {};
bool operator<(const Paper& other) { return true; }
bool operator<(const Scissors& other) { return false; }
std::string str() const override { return "Rock"; }
};
class Paper : public Sign {
public:
Paper(const int v): Sign(v) {};
bool operator<(const Rock& other) { return true; }
bool operator<(const Scissors& other) { return false; }
std::string str() const override { return "Paper"; }
};
class Scissors : public Sign {
public:
Scissors(const int v): Sign(v) {};
bool operator<(const Rock& other) { return false; }
bool operator<(const Paper& other) { return true; }
std::string str() const override { return "Scissors"; }
};
Sign from_str(const int value,const std::string& s)
{
if(s == "R")
return Rock(value);
if(s == "P")
return Paper(value);
if(s == "C")
return Scissors(value);
throw 1;
}
int main()
{
int N;
cin >> N; cin.ignore();
std::vector<Sign> s{};
for (int i = 0; i < N; i++) {
int NUMPLAYER;
string SIGNPLAYER;
cin >> NUMPLAYER >> SIGNPLAYER; cin.ignore();
s.emplace_back(from_str(NUMPLAYER,SIGNPLAYER));
}
}
此时,我真的不明白为什么我不能使用 Sign
作为工厂方法的返回值,该方法返回具体类型并将其放置在我的数据堆中。
如果我添加到基类
virtual std::string str() const { return "Sign"; };
我只会得到基类的打印输出。
解决方法
您在 from_str
的返回类型和 vector <Sign>
中都受到 object slicing 的困扰。
喜欢与否,您将不得不使用指针,但如果您使用智能指针,那么痛苦就会消失。因此,首先像这样更改您的 from_str
函数:
std::unique_ptr <Sign> from_str(const int value,const std::string& s)
{
if(s == "R")
return std::make_unique <Rock> (value);
if(s == "P")
return std::make_unique <Paper> (value);
if(s == "C")
return std::make_unique <Scissors> (value);
throw 1;
}
然后将您的向量更改为:
std::vector<std::unique_ptr <Sign>> s{};
这就是您需要更改的全部内容。您使用 std::unique_ptr
这一事实可以解决所有内存管理问题。
没有分配,您可以使用std::variant
:
struct Rock
{
std::string str() const { return "Rock"; }
};
struct Paper
{
std::string str() const { return "Paper"; }
};
struct Scissors
{
std::string str() const { return "Scissors"; }
};
using Sign = std::variant<Rock,Paper,Scissors>;
bool winSigns (Paper,Rock) { return true; }
bool winSigns (Rock,Scissors) { return true; }
bool winSigns (Scissors,Paper) { return true; }
template <typename Sign1,typename Sign2>
bool winSigns (Sign1,Sign2) { return false; }
Sign from_str(const std::string& s)
{
if (s == "R")
return Rock{};
if (s == "P")
return Paper{};
if (s == "C")
return Scissors{};
throw 1;
}
int main()
{
std::string SIGNPLAYER1;
std::cin >> SIGNPLAYER1;
Sign sign1 = from_str(SIGNPLAYER1);
std::string SIGNPLAYER2;
std::cin >> SIGNPLAYER2;
Sign sign2 = from_str(SIGNPLAYER2);
std::visit([](auto lhs,auto rhs){
std::cout << lhs.str() << "versus" << rhs.str() << std::endl;
if (winSigns (lhs,rhs)) std::cout << "player1 wins\n";
else if (winSigns (rhs,lhs)) std::cout << "player2 wins\n";
else std::cout << "Draw\n";
},sign1,sign2);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。