2013-04-03 125 views
0

我有以下類:列表轉換類於母公司

class A 
{ 
public: 
    A(); 
    virtual void doSomething() const; 
}; 

class B : public A 
{ 
public: 
    B(); 
    void doSomething() const; 
}; 

然後,我有功能:

void putToList(const A &a) 
{ 
    a.doSomething(); // this one depends on what was set as argument A or B class (putToList(A()) or putToList(B())) 
    std::list<A> As; 
    As.push_back(a); 
    As.back().doSomething(); //this always calls doSomething from A 
} 

我的問題是,從列表中取whyafter,對象是和如何預防改變類型,如果我傳遞給函數的對象是B類,則使它成爲B.

+2

打哈欠哈欠切片 – 2013-04-03 22:58:43

+1

@LightnessRacesinOrbit,太糟糕了我只有一個投票給予。 – 2013-04-04 00:56:47

回答

5

As的類型是std::list<A>。它存儲A對象。如果您嘗試放入B對象,則將切片爲,您將只獲得其中的A部分。無論何時從列表中獲取元素,它都是一個A對象,因此您調用的任何函數都將是A的成員函數。

有兩種方法可以在C++中獲得多態行爲:指針或引用。例如,你可以在列表中存儲指向A

std::list<A*> As; 
As.push_back(&a); 
As.back()->doSomething(); 

當然,最好是把它包起來的智能指針。請使用std::list<std::reference_wrapper<A>>代替。

3

這是對象切片問題,其中B實例將被切成的A實例的很好的例子,因而失去了什麼是具體的B(見What is object slicing?)。

在使用對象列表時,您不會實現此類運行時多態性。你可以使用指針的列表,而不是:

std::list<A*> As; 
As.push_back(new B()); 
As.back()->doSomething(); // method of B is invoked 

或者還甚至更好:利用RAII對於再次和使用智能指針代替裸指針(即A*喜歡在我的例子所示)。

+1

請不要存儲原始指針。 – 2013-04-03 23:01:17

+0

@LightnessRacesinOrbit:夠公平的。我添加了一個關於它的說明:) – LihO 2013-04-03 23:03:04