【问题标题】:Using overriden function in base class constructor for derived class在派生类的基类构造函数中使用覆盖函数
【发布时间】:2020-01-16 13:16:53
【问题描述】:

我对 C++ 编程非常陌生,所以我想编写一些简单的代码来适应语法。我暂时故意忽略了指针和引用。

在编码期间,我正在练习继承,我想创建一个代表手牌的类 Hand。基类有一个名为 update() 的函数,用于在构造时初始化“total”和“notation”属性。此外,可以使用 add() 函数向手牌添加卡片,该函数将卡片添加到手牌并触发 update() 以适当地更新属性。

#include<vector>

class Hand
{
public:
    std::vector<int> cards;
    int total;
    std::string notation; // Abbreviated notation of the object
    // Constructor
    Hand(std::vector<int> cards);
    void update();
    void add(int card);
}

Hand::Hand(std::vector<int> cards)
{
    this->cards = cards;
    update();
}

void Hand::update()
{
    total = 0;
    notation += "{ ";
    for (int card: cards)
    {
        total += card;
        notation += std::to_string(card) + " ";
    }
    notation += "}";
}

void Hand::add(int card)
{
    cards.push_back(card);
    update();
}

接下来,我想创建一个更具体的 Hand 类,称为 StandHand,它的功能与 Hand 相同,但它还有一个变量,当总数达到特定值时会发生变化。

最初我以为我可以编写如下所示的子类,但是唉。

class StandHand : public Hand
{
public:
    int stand;
    StandHand(std::vector<int> cards, int stand);
    void update();
}

StandHand::StandHand(std::vector<int> cards, int stand) : Hand(cards)
{
    this->stand = stand;
    updateHand();
}

void StandHand::update()
{
    Hand::update();
    notation += stand <= total ? " (stand)" : "";
}

但是当我在 StandHand 对象上调用 add() 方法时,它不使用 StandHand::update() 方法,而是使用基本的 update() 方法。如何确保 add() 方法在 Hand 的子类中使用时使用该子类的 update() 函数?

【问题讨论】:

  • 你的 C++ 书应该有一章关于虚拟继承。您可以在此处找到有关如何执行此操作的其他信息。
  • 您需要了解virtual 的功能:virtual void update() 可以解决问题。

标签: c++ function inheritance constructor virtual


【解决方案1】:

对于代码中的初学者,没有重载函数。派生类中update的声明隐藏了基类中同名函数的声明。

由于在基类中声明了成员函数add,因此函数名称update也在基类中搜索。

将函数update声明为虚函数。

class Hand
{
public:
    // ...
    virtual void update();
};

class StandHand : public Hand
{
public:
    // ///
    void update() override;
};

【讨论】:

    【解决方案2】:

    您的代码中有两个问题,首先需要将基类中的void update(); 声明为virtual,以便编译器知道派生类可能会覆盖并使用它。

    virtual void update();
    // add "=0;" if there is no base version of update()
    

    并在派生类中写入

    void update() override;
    //override is unnecessary but recommended
    //it verifies that you do indeed overload a method from a base class
    

    第二个问题,不能在派生类的基类的构造函数中调用方法。发生的情况是调用虚拟基方法会导致调用基版本而不是派生版本。想一想:派生对象尚未构造,但您已经调用了它的方法之一?这没有任何意义。

    【讨论】:

    • 我的基类在构造时不是也在调用函数吗?还是我错过了什么?
    • @JansthcirlU 构造函数被调用以“从基到派生”。只有在派生类的构造函数中,虚拟方法才会被覆盖;在此之前,基本构造函数不知道谁会覆盖它或是否有任何东西。您可能想查看虚函数调用是如何实现的,以便更好地了解行后发生的情况。
    • 即使从构造函数调用 this 类的虚函数也会导致调用基类之一。
    猜你喜欢
    • 2016-07-19
    • 2021-11-11
    • 2018-07-21
    • 2018-07-16
    • 1970-01-01
    • 2015-08-18
    • 2016-12-20
    • 2020-11-28
    • 2012-09-28
    相关资源
    最近更新 更多