2011-04-24 91 views
3

這是我的問題: 在我的GUI中,有幾種類型的偵聽器。它們存儲在std::vector<WhateverListener*>std :: remove不會從std :: vector中刪除

在我的GUI,我呼籲的方法removeListeners,它看起來像這樣:

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

基本上,我不認爲它應該不管我怎麼投它;他們只是指針。我認爲std::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轉換爲該類型。但我認爲它只是比較指針,如果他們==它會刪除它?

+4

鑄造告訴編譯器「*我知道這個變量的類型,即使你不知道。」你不應該把一個指針指向一個不是真的類型。每個'Widget *'同時傳遞給'removeListeners()'一個焦點,鼠標,鍵盤和小部件監聽器嗎? – 2011-04-24 23:23:16

+3

更好地修改標題以提及'erase',因爲我和其他人可能首先認爲這只是另一個不理解「刪除」如何工作的問題。 ;) – Xeo 2011-04-24 23:25:50

+0

@Xeo:是的,我在閱讀帖子之前輸入了_that_答案,然後在5秒內刪除它:) – sehe 2011-04-24 23:44:00

回答

1

問題的根源似乎是不正確的設計。需要按照您的意圖進行投射意味着該功能位於錯誤的位置。從你的文章中不清楚Widgets和不同類型的Listener類之間的關係。

您需要重新考慮從哪裏調用removeListeners函數,而不是將它放入基類析構函數中,您應該將它放入類的析構函數中,該類實際上知道它是哪種類型的偵聽器(並且僅調用正確的)。

如果沒有詳細瞭解類之間的關係,就很難更具體。一般來說,如果你必須演員,你應該問自己是否有更好的方法來完成它迫使你演員。

+0

就是這樣,謝謝! – jmasterx 2011-04-25 03:03:53

2

恐怕你可能由對象標識和虛基類在C++

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

基本上被挨叮咬,轉換指針polymorphics鹼基,不能保證以導致相同的指針值(當投到(void *)eg)。

應該工作,只要你存儲完全相同的指針爲你拆卸過程中它轉換爲,但不看更多的代碼/部件類層次結構的我不能肯定。

+0

因此,我應該在刪除前動態投射然後 – jmasterx 2011-04-24 23:34:35

+0

是的,但僅限於您插入它們的確切類型。我個人認爲演員陣容是一種氣味,但你絕對應該考慮dynamic_cast <>這種場景 – sehe 2011-04-24 23:43:26