Std::remove不是从Std::vector中移除

std::remove is not removing from std::vector

本文关键字:Std vector remove      更新时间:2023-10-16

我的问题是:在我的GUI中,有几种类型的监听器。它们存储在std::vector<WhateverListener*>

在我的GUI中,我有一个名为removeListeners的方法,它看起来像这样:

void Widget::removeListeners( Widget* widget )
{
    removeFocusListener((FocusListener*)widget);
    removeMouseListener((MouseListener*)widget);
    removeKeyboardListener((KeyboardListener*)widget);
    removeWidgetListener((WidgetListener*)widget);
}

基本上,我不认为我如何投射它应该是重要的;它们只是指针。我认为std::remove只是比较指针,因此,如果我提供一个小部件*那么它不应该影响任何东西(我认为)。

remove函数是这样的:

void Widget::removeWidgetListener( 
                                    WidgetListener *listener )
{
    widgetListeners.erase(
        std::remove(widgetListeners.begin(),
        widgetListeners.end(), listener),
        widgetListeners.end());
}
因此,在Widget析构函数中,我遍历小部件的子节点并调用removeListeners():
Widget::~Widget(void)
{
    for(std::vector<Widget*>::iterator it = getChildBegin();
        it != getChildEnd(); ++it)
    {
        (*it)->removeListeners(this);
        (*it)->parentWidget = NULL;
        (*it)->_container = NULL;
    }
}

它不工作。在一个Widget上调用delete后,它正在监听它的子控件,子控件仍然有监听器。

但是,如果我直接调用remove方法,并且小部件继承自侦听器,则它可以工作:

Widget::~Widget(void)
{
    for(std::vector<Widget*>::iterator it = getChildBegin();
        it != getChildEnd(); ++it)
    {
        (*it)->removeWidgetListener(this);
        (*it)->parentWidget = NULL;
        (*it)->_container = NULL;
    }
}

那么为什么一个有效而另一个无效呢?我发现的唯一区别是,在第一个示例中,我将Widget强制转换为该类型。但我认为它只是比较指针,如果它们是==它会删除它吗?

我担心你可能会被c++中的对象标识和虚拟基类刺痛

http://www.parashift.com/c + + -faq-lite/multiple-inheritance.html

基本上,将指针转换为多态基,不能保证产生相同的指针值(例如,当转换为(void*)时)。

应该工作,只要你存储完全相同的指针类型,你转换成在删除,但我不能确定没有查看更多的代码/小部件类层次。

问题的根源似乎是一个不正确的设计。需要像您正在做的那样强制转换意味着函数在错误的位置。从你的帖子中不清楚Widgets和不同类型的Listener类之间的关系是什么。

您需要重新考虑从哪里调用removelistener函数,而不是将其放在基类析构函数中,您应该将其放在实际知道侦听器类型的类的析构函数中(并且只调用正确的侦听器)。

如果不了解类之间关系的更多细节,就很难更具体。一般来说,如果你必须强制转换,你应该问问自己,是否有更好的方法来完成强迫你强制转换的事情。