【问题标题】:How can I declare an instance of any inherited class?如何声明任何继承类的实例?
【发布时间】:2020-11-12 13:29:16
【问题描述】:

我开始用 C++ 编写一个带有类的简单程序来熟悉 OOP。 我写了一个 Game 类,它将 Player 和 Unit 类的实例作为属性:

#ifndef GAME_HPP
#define GAME_HPP

#include "Unit.hpp"
#include "Player.hpp"

class Game
{
public:
    //ATTRIBUTES
    Player player;
    Unit mob;
    
    //CONSTRUCTORS
    Game(Player, Unit){};
    
    //METHODS
    std::string get_n_chars(char, int);
    void print_player_character_panel();
    void print_enemy_character_panel();
    void print_character_panels();

};

#endif // GAME_HPP

我希望“mob”属性采用任何继承的“Unit”类,即

class Goblin : public Unit
{...
int main()
{    
    Player hero{"Boi"};
    Goblin goblin;

    Game game1(hero, goblin);
    
    return 0;
}

但是当我这样做时,“mob”只有“单元”的属性和方法。 像这样:

https://i.stack.imgur.com/nShv3.png

甚至构造函数的属性也发生了变化:

https://i.stack.imgur.com/mPrW2.png

我能否以某种方式将任何继承的“Unit”类的实例声明为 mob 属性,并使其保持该类的实例而不是“Unit”。

【问题讨论】:

  • 您已成为object slicing 的受害者。多态性只能通过指针或引用起作用。
  • 你需要std::unique_ptr<Unit>。或者指向Unit + new 的指针(后者可以很好地练习,但不建议在实际代码中使用)。
  • @HolyBlackCat:你根本不知道 OP 需要任何指针。
  • @einpoklum OP 要求提供一个变量来存储从Unit 派生的任何类。这需要一个指针(除非您接受一些权衡,例如提前列出所有类以获取 std::variant)。
  • 这能回答你的问题吗? What is object slicing?

标签: c++ class inheritance


【解决方案1】:

tl;dr:考虑使用变体。

我能否以某种方式将任何继承的“Unit”类的实例声明为 mob 属性,并使其保持该类的实例而不是“Unit”。

只要您愿意在编译时说明哪些类继承了Unit,那么 - 是的,差不多。您可以使用std::variant - 这是一种更高级的工会形式。

假设您的单位类型为GoblinTrollWizard,则为:std::variant<Goblin, Troll, Wizard>

但是请注意,变体类与所有变体类型通用的基类不同。换句话说,std::variant<Goblin, Troll, Wizard> 可能是我们心目中的一个单元,但就 C++ 编译器而言,它不是 Unit。因此,您必须做一些工作才能运行采用 Unit&Unit*Unit 方法的代码。

这里有一个使用 std::variant 的教程,如果你以前没有使用过,我推荐它:

Simplify C++: Modern C++ Features – std::variant and std::visit

【讨论】:

    猜你喜欢
    • 2019-02-07
    • 2022-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多