【问题标题】:How to make convince compiler object will be an of a derived class?如何使编译器对象成为派生类的一个?
【发布时间】:2015-12-08 07:34:15
【问题描述】:

我在继承方面遇到问题,我不知道这是否是设计缺陷,如果是,如何解决。我有一个包含四个类的案例:两个基类和两个派生类。我将使用另一个示例:

class Player {  // base class for a player in general
    ...
}

class Game {    // base class for a game in general
    ...
    Player * players;    // dynamically allocated at run-time
    ...
}

class BaseballPlayer : public Player {
    ...
    void hitHomeRun();
    ...
}

class BaseballGame : public Game {
    ...
        ...
           players[i].hitHomeRun(); // this causes compiler error
}

我得到的错误是因为方法没有在基类中定义,但是数组是基类类型的。在BaseballGame 类中,只有BaseballPlayers 被加载到数组中,但我无法说服编译器。这是选角问题吗?我如何保证编译器 players 将充满正确的对象?我可以在派生类中用BaseballPlayer * team 覆盖Player * players 成员本身吗?

【问题讨论】:

  • 搜索并阅读有关downcasting的信息。
  • 我做了这件事,我写了一个构造函数 BaseBallPlayer(Player&) ,然后就投了它。它可以编译,但我担心它不会对原始对象执行突变...
  • 使用 C++ 容器,例如 std::arraystd::vector
  • @MichaelLongauer,该构造函数创建了一个新对象,您不希望这样,您只想强制转换现有对象以告诉编译器它的类型(如上所述使用dynamic_cast,或如果您确定BaseballGame 中的所有玩家都是BaseballPlayers,那么您可以使用static_cast)。但是,n.m. 下面的答案是一个更干净的选项,不需要强制转换。
  • 是的,你有一个巨大的设计缺陷。您的设计不是面向对象的,因为Player 似乎没有被设计为面向对象的基类。它没有虚函数; Player 的客户必须手动查询子类型才能做一些有用的事情。只需很少的额外工作,您就可以消除设计中的所有基类。

标签: c++ inheritance polymorphism


【解决方案1】:

这是非常标准的。

template <typename P>
class Game {
   std::vector<P> players;
...

class Player ...
class BaseballPlayer : public Player ...

class BaseballGame : public Game<BaseballPlayer> ...

【讨论】:

    【解决方案2】:

    是的,这似乎是一个设计缺陷。你的玩家只会是BaseBallPlayersCricketPlayers。而 Player 将仅包含有关玩家的常见信息,即。年龄,姓名,出生日期等,而其专业化将包含有关他的记录的信息。

    两个建议。 1>class Game:每个游戏都有玩家。将 Player * players; 更改为 Player * **players; 。所以 Game 将包含动态分配的指向玩家的指针数组。

    2> class BaseBallPlayerclass player。覆盖BaseBallPlayer::hitHomeRun 并声明与virtual void Player::hitHomeRun 相同。

    并将呼叫更改为players[i].hitHomeRun();作为dynamic_cast&lt;BaballPlayer*&gt;(players[i])-&gt;hitHomeRun();virtual 覆盖将调用 BaseBallPlayer::hitHomeRundynamic_cast 仅适用于虚拟继承或基类应包含至少一个虚拟方法。

    【讨论】:

    • 这两个建议对我来说都没有意义。 Game 已经包含一个动态分配的玩家数组,您的建议有什么帮助?以及使用虚拟基类有什么帮助?
    • @jonathan:好吧,如果你看到我创建了“指向玩家的指针”而不是玩家的动态数组。那么它也可以是“指向玩家的指针”的向量。如果你调用播放器的任何函数,它实际上会调用一个虚函数的派生类方法。
    • 是的,我知道虚函数是如何工作的。无需更改为指针数组即可。 Player* players = new BaseballPlayer[2]; static_cast&lt;BaseballPlayer*&gt;(players)[1].hitHomeRun(); 即使没有虚函数也能正常工作。如果您要对派生类型使用强制转换,那么向基类添加虚拟是没有意义的。 (我看到你已经修复了使用虚拟基类的建议,这根本没有帮助)。
    猜你喜欢
    • 1970-01-01
    • 2013-09-28
    • 2012-03-05
    • 2013-12-09
    • 2012-12-11
    • 2011-03-22
    • 1970-01-01
    • 1970-01-01
    • 2020-03-13
    相关资源
    最近更新 更多