2010-03-06 114 views
3

我有以下兩個類,一個從另一C++繼承,基函數重寫時

Class A{ 
    void print(){cout << "A" << endl;} 
} 

Class B : A{ 
    void print(){cout << "B" << endl;} 
} 
Class C : A{ 
    void print(){cout << "C" << endl;} 
} 

繼承然後在另一個I類有以下仍被稱爲:

vector<A> things; 
if (..) 
    things.push_back(C()); 
else if (..) 
things.push_back(B()); 

things[0].print(); 

這總是打印A
我想打印B或C,具體取決於我向矢量添加了哪些東西
我該如何做到這一點?
我已經試過抽象,但我不完全知道如何在C++中使用它,它一直沒有工作對我來說

回答

8

如上所述,您需要使用virtual函數來啓用多態行爲,並且不能直接按值存儲類vector

當您使用std::vector<A>時,您按值存儲,因此您添加的對象(例如,通過push_back()被複制到A的一個實例,這意味着你失去了派生的部分對象。這個問題被稱爲object slicing

正如已經建議你可以避免通過存儲指針(或智能指針)基類,所以只有指針被複制到vector

std::vector<A*> things; 
things.push_back(new B()); 
// ... use things: 
things[0]->print(); 

// clean up later if you don't use smart pointers: 
for(std::vector<A*>::iterator it = things.begin(); it != things.end(); ++it) 
    delete *it; 
+2

請記住,如果在使用向量過程中發生任何異常,您將發生泄漏。一個解決方案當然是使用Boost的指針庫。但是,如果這是不可能的,一個非常簡單的解決方案可能是創建一個'pointer_vector '類,該類有一個可以使用'get'函數訪問的私有'vector '。這個包裝器的析構函數執行刪除操作。現在這些對象被保證被刪除。 – GManNickG 2010-03-06 01:25:11

3

您需要聲明的功能虛擬您的基類,在這種情況下的類a:

class A{ 
    virtual void print(){cout << "A" << endl;} 
} 

即使你不在這些(但你可以)寫入虛擬內容,其他類也會選擇它。

虛擬告訴編譯器該函數可以被覆蓋。如果您不使用虛擬,則稱爲隱藏,並按照您的發現進行不同的工作。

+0

當我這樣做,它仍然不工作 ,如果我讓他們純虛函數,然後我得到一個錯誤,因爲矢量實例化抽象類的對象 – 2010-03-06 00:50:18

+0

另一個答案是*部分*正確的。這是錯誤的,它說你不能「存儲」矢量中的一個對象。你可以做到這一點,但是當你這樣做時,你只會讓你的矢量存儲A對象,即使你試圖將B和C放在那裏,矢量實際上會創建一個A對象並將B或C複製到它中。您需要在向量中存儲指向A的指針以獲取所需的行爲。 – SoapBox 2010-03-06 01:05:38

8

1)你必須在A級申報的print()作爲虛擬

2)你的載體是不正確的 - 你不能存儲在那裏實際的A類對象;你需要存儲指向它們的指針以獲得正確的行爲(並且你將不得不在後面清理它們)和/或使用類似boost :: shared_ptr的東西。

+1

我剛纔說的:)多態性大多隻在使用指針/引用時纔有意義...... – 2010-03-06 00:53:51