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

C++ 如何正确覆盖虚拟方法以添加功能?,c++,qt,oop,polymorphism,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.e

在基类中,我有一个简单的按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::GameEntityList::通过运动id\u virt(常量字符串和运动id)删除运动
{
对于(QList::iterator it=m_game_list.begin();
it!=m_game_list.end();)
{
GameEntity*tmp=(*it);
如果(tmp->get_sport_id()==sport_id)
{
它=m_游戏列表。擦除(它);
删除tmp;
tmp=0;
}
其他的
{
++它;
}
}
}
在派生类中。压倒

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
}
void Ui::GameWidgetList::通过\u sport\u id\u virt(const QString&id)删除\u games\u
{
QList::迭代器it;
for(it=m_game_list.begin();it!=m_game_list.end();)
{
GameWidget*tmp=动态施法(*it);
Q_断言(tmp!=NULL);
如果(tmp->get_sport_id()==id)
{
它=m_游戏列表。擦除(它);
在监视器(tmp->get_id(),this->get_monitor_number())中发出移除游戏的命令;//需要发出此信号
删除tmp;
tmp=0;
}
其他的
{
++它;
}
}
this->set_number_of_games(m_games_list.size());//需要调用此函数
}

我无法找到避免代码重复的方法。我应该有一个空的virtualnotify()函数,并在删除元素后调用它吗?这样,我就可以重写派生中的notify()来执行此任务。这是一个可以接受的决定吗?在基类中实现按id删除是否不必要?

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

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
}
void Ui::GameEntityList::通过运动id虚拟删除游戏(const QString&id)
{
QList::迭代器it;
for(it=m_game_list.begin();it!=m_game_list.end();)
{
如果(tmp->get_sport_id()==id)
{
它=m_游戏列表。擦除(它);
此->打开擦除(tmp);//可自定义
删除tmp;
tmp=0;
}
其他的
{
++它;
}
}
此->on_finish();//可自定义
}

get_id()
是否只属于
GameWidget
?你为什么要动态施法?@dwcanillas我想,
GameEntity
源于
GameWidget
@MateuszGrzejek,仅仅因为一个源于另一个并不意味着他需要施法。他需要施法,因为他执行向下施法。@MateuszGrzejek如果施法没有提供任何有用的东西,他不需要向下施法。如果他在这里调用的所有方法都是虚拟的或可从基类访问的,则不需要强制转换_ASSERT@dwcanillas我提供的是问题的答案,而不是回顾OP的代码。将这两种方法结合到一个有效的解决方案中是您答案的一部分。在组合这些函数之前,强制转换和断言都不是问题。啊,是的,我的错,我以为我是在从
GameEntity
复制
remove\u games\u by\u sport\u id\u virt()
的主体。修好了,谢谢!