2011-04-24 2 views
3

Voici mon problème: Dans mon interface graphique, il existe plusieurs types d'écouteurs. Ils sont stockés dans std::vector<WhateverListener*>std :: remove ne supprime pas de std :: vector

Dans mon interface graphique, j'ai une méthode appelée removeListeners et il ressemble à ceci:

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

Fondamentalement, je ne pense pas que ce devrait importe comment je l'ai jeté; ce ne sont que des pointeurs. Je pense que std::remove compare simplement les pointeurs, donc si je fournis un widget *, cela ne devrait rien affecter (je pense).

Comment les fonctions remove look est quelque chose comme ceci:

void Widget::removeWidgetListener( 
            WidgetListener *listener) 
{ 
    widgetListeners.erase(
     std::remove(widgetListeners.begin(), 
     widgetListeners.end(), listener), 
     widgetListeners.end()); 
} 

Ainsi, dans le destructor Widget, j'itérer les enfants du widget et appelle removeListeners():

Widget::~Widget(void) 
{ 

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

} 

Il ne fonctionne pas. Après avoir appelé supprimer sur un Widget qui écoutait ses enfants, les enfants avaient encore des auditeurs.

Cependant, si j'appelle les méthodes directement remove et le widget hérite de l'auditeur, il fonctionne:

Widget::~Widget(void) 
{ 

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

} 

Alors, pourquoi ne un travail et pas l'autre? La seule différence que je remarque est que dans le premier je lance un Widget à ce type. Mais je pensais que ce serait juste comparer les pointeurs et si elles étaient == il l'enlèverait?

+4

La conversion indique au compilateur "* I * connaître le type de cette variable, même si ce n'est pas le cas." Vous ne devriez pas lancer un pointeur sur un type qui n'est pas vraiment.Est-ce que chaque 'Widget *' est passé à 'removeListeners()' simultanément un focus, une souris, un clavier et un écouteur de widget? –

+3

Mieux vaut modifier le titre pour mentionner «effacer», car moi et peut-être d'autres personnes ont d'abord pensé que c'était juste une autre question qui ne comprenait pas comment «supprimer» fonctionne. ;) – Xeo

+0

@Xeo: Yup, j'avais tapé _that_ réponse avant de lire le post, puis l'ai supprimé en 5 secondes :) – sehe

Répondre

1

La racine de votre problème semble être une conception incorrecte. Le besoin de lancer comme vous le faites implique que la fonction est au mauvais endroit. Il n'est pas clair dans votre message quelle est la relation entre les Widgets et les différents types de classes d'écoute. Vous devez repenser l'endroit où vous appelez la fonction removeListeners. Au lieu de la placer dans le destructeur de classe de base, vous devez le placer dans le destructeur de la classe qui connaît réellement le type d'écouteur (et appeler uniquement la bonne).

Il est difficile d'être plus précis sans avoir plus de détails sur les relations entre vos classes. En général, si vous devez lancer, vous devriez vous demander s'il existe une meilleure façon d'accomplir ce que vous êtes obligé de lancer.

+0

C'était tout, merci !!!! – jmasterx

2

Je crains que vous pourriez faire piquer par l'identité des objets et des classes de base virtuelles en C++

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

Fondamentalement, la conversion des pointeurs vers des bases de polymorphes, n'est pas garanti pour résultat des valeurs de pointeur identiques (lorsque jeté à (vide *) par exemple).

Il devrait fonctionner aussi longtemps que vous enregistrez exactement le même pointeur de type que ce que vous jeté à lors de l'enlèvement, mais je ne peux pas être sûr sans regarder plus de votre code/widget de hiérarchie de classe .

+0

Donc je devrais lancer dynamiquement avant le retrait puis – jmasterx

+0

Yup, mais seulement au type exact que vous les insérez comme . Personnellement, je pense que les moulages sont une odeur, mais vous devriez certainement considérer dynamic_cast <> pour ce type de scénario – sehe

Questions connexes