如何正确覆盖虚拟方法以添加功能?

时间:2015-05-01 17:26:19

标签: c++ qt oop polymorphism

在基类中我通过id虚函数进行简单删除,但是在派生类中我还需要在删除后发出一个信号(notify)。

在基类中。以下是函数

的默认实现
void Ui::GameEntityList::remove_games_by_sport_id_virt(const QString &sport_id)
{
    for(QList<GameEntity*>::iterator it = m_game_list.begin();
        it != m_game_list.end();)
    {
        GameEntity* tmp = (*it);
        if(tmp->get_sport_id() == sport_id)
        {
            it = m_game_list.erase(it);
            delete tmp;
            tmp = 0;
        }
        else
        {
            ++it;
        }
    }
}

在派生类中。覆盖

void Ui::GameWidgetList::remove_games_by_sport_id_virt(const QString &id)
{
    QList<GameEntity*>::iterator it;
    for(it = m_game_list.begin(); it != m_game_list.end();)
    {
        GameWidget* tmp = dynamic_cast<GameWidget*>(*it);
        Q_ASSERT(tmp != NULL);
        if(tmp->get_sport_id() == id)
        {
            it = m_game_list.erase(it);
            emit remove_game_in_monitor(tmp->get_id(),     this->get_monitor_number()); // need to emit this signal
            delete tmp;
            tmp = 0;
        }
        else
        {
            ++it;
        }
    }
    this->set_number_of_games(m_game_list.size()); // need to call this function
}

我无法管理避免代码重复的方法。我应该有一个空的虚拟notify()函数并在删除元素后调用它吗?这样我可以覆盖派生的notify()来完成这项工作。这是可以接受的决定吗?在基类中实现删除id是不必要的吗?

1 个答案:

答案 0 :(得分:3)

在您的情况下,重复代码的数量并没有那么糟糕。但是,无论如何,在这种情况下,您可能希望将此功能设置为非虚拟,并将此可自定义功能移至其他虚拟功能:

class GameEntityList
{
private:
    virtual void on_erase(GameWidget* w)
    {
        //empty
    }

    virtual void on_finish(GameWidget* w)
    {
        //empty
    }

    //others
};

class GameWidgetList : public GameEntityList
{
private:
    virtual void on_erase(GameWidget* w)
    {
        remove_game_in_monitor(w->get_id(), this->get_monitor_number());
    }

    virtual void on_finish(GameWidget* w)
    {
        this->set_number_of_games(m_game_list.size());
    }

    //others
};

然后:

void Ui::GameEntityList::remove_games_by_sport_id_virt(const QString &id)
{
    QList<GameEntity*>::iterator it;
    for(it = m_game_list.begin(); it != m_game_list.end();)
    {
        if(tmp->get_sport_id() == id)
        {
            it = m_game_list.erase(it);

            this->on_erase(tmp); //customizable

            delete tmp;
            tmp = 0;
        }
        else
        {
            ++it;
        }
    }

    this->on_finish(); //customizable
}