2013-04-03 124 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