2011-06-05 56 views
5

假設我有與虛擬功能和實現以不同的方式在虛擬函數的派生類的類的虛擬功能。假設我也有一個用於存儲派生類的基類的向量。如何在向量中執行派生類的虛函數而不事先知道派生類是什麼?說明問題的最小代碼:C++:調用派生類

#include <iostream> 
#include <vector> 

class Foo { 
public: 
    virtual void do_stuff (void) { 
     std::cout << "Foo\n"; 
    } 
}; 

class Bar: public Foo { 
public: 
    void do_stuff (void) { 
     std::cout << "Bar\n"; 
    } 
}; 

int main (void) { 
    std::vector <Foo> foo_vector; 
    Bar bar; 

    foo_vector.resize (1); 
    foo_vector [0] = bar; 

    bar.do_stuff();   /* prints Bar */ 
    foo_vector [0].do_stuff(); /* prints Foo; should print Bar */ 
    return 0; 
} 
+7

也許使用'的std ::矢量'(由指針,或參照),以避免物體切片?否則,當你將'bar'對象賦值給vector時,它就被分割了(一個新的'Foo'被創建並存儲在vector中,而不是你的'bar'),這可能不是你想要的。不過,使用指針會使代碼更復雜。 – rwong 2011-06-05 00:21:34

回答

14

您不能。在矢量對象將一直切片 - 任何派生類實例的數據將被砍掉,所以調用該方法將是一個極壞的主意。

如果,在另一方面,你有指針向量至基部,那麼你只需調用虛擬方法,和派生類版本將被調用。

+2

謝謝。我不知道切片,你的建議解決了這個問題。 – Adetque 2011-06-05 02:05:25

2

你實際上是調用類是不是一類吧,而是一類Foo的。你在做什麼在foo_vector [0] = bar;是一個隱式operator =的調用,它正在盡力使事情變得聰明。內存空間仍然是Foo的大小,所以它永遠不會是一個Bar。

0

使用虛擬功能,你使用指針的對象。這種方式的確切功能在運行時調用(「我將如何執行的矢量派生類的虛函數事先不知道派生類是什麼?」你是什麼意思這裏可能是「運行時間」)。

將函數標記爲虛擬的用法是,您要求編譯器在運行時推遲或計算調用該函數的對象的「TYPE」,而不是通常的「編譯時」方式。這是通過使用指向對象的指針來實現的。所以把它放在一個簡單的行中「使用指向對象的指針來使用虛函數」。