我是C ++的新手,所以我决定创建一个纸牌游戏。我想将派生的卡对象存储为向量中的卡*。当有人画一张卡片时,我想从矢量中取出第一个物体并将其返回。这是事情变得棘手的地方,当我这样做时,我想将它从Card *转换回原来的派生类型。我读到如果没有明确的演员表示不可能在c ++中保持低调,我想要重申这一点或找到解决方案。
卡类
class Card
{
public:
int Cost;
string Name;
string Description;
Card() {}
Card(int Cost, string Name, string Description) : Cost(Cost), Name(Name), Description(Description) {}
};
灵魂等级
class Soul : public Card
{
public:
int Attack;
int Defense;
Soul(int Cost, string Name, string Description, int Attack, int Defense) :Card(Cost, Name, Description), Attack(Attack), Defense(Defense) {}
void Attacking(Soul* DefendingSoul);
};
最后是特定卡片类的示例
class Fire_Spirit : public Soul
{
public:
Fire_Spirit() : Soul(1, "Fire Spirit", "A lonely spirit born from the inferno.", 2, 1) {}
~Fire_Spirit();
};
甲板等级
class Deck
{
public:
Deck();
~Deck();
Card* Draw();
void Shuffle();
void Add(Card* cardToAdd);
void PrintDeck();
static vector<Card*> Cards;
};
绘制方法
auto Deck::Draw() -> Card*
{
auto temp = Cards.front();
Cards.erase(Cards.begin());
return temp;
}
理想情况下,我只想在这里返回auto,但我读到我需要为方法定义auto的返回类型(我很乐意以其他方式显示)
我想从Card *转到Fire_Spirit(*?)或任何其他特定卡类。我知道我可以做一个巨大的转换声明,但必须有更好的方法吗?
答案 0 :(得分:1)
根据评论中提供的反馈,我会采用这样的解决方案:
class Card {
private:
CardKind kind_;
std::fucntion<void (Card &)> attack_;
std::function<void (Card &)> effectFunc_;
std::unordered_map<std::string, boost::any> properties;
Card(CardKind kind, std::function<void (Card &)> attackFunc,
std::function<void (Card &)> effectFunc);
};
答案 1 :(得分:0)
通过指针存储容器会在将类型放入容器时丢失类型信息。类型擦除的关键在于以统一的方式处理元素,而类层次结构就是这样。
如果您想要返回类型信息,则需要使用typeid(my_var)
或dynamic_cast
询问运行时。 确保您的基类具有虚拟析构函数。这将为您提供原始类型:
auto temp = cards.front();
if (typeid(temp) == typeid(MyDerivedCard)) {
}
else if (...) {
}
或
if ((MyDerivedCard * c = dynamic_cast<MyDerivedCard>(temp)) != nullptr) {
//Use derived
}
...
P.S。:您可以使用std::unique_ptr<Card>
存储卡片。他们将自动删除内存并清除所有权。在http://en.cppreference.com/w/cpp/memory/unique_ptr