List将类转换为父级

时间:2013-04-03 22:54:44

标签: c++ polymorphism

我有以下课程:

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
}

我的问题是,从列表中取出后,对象是A,如果阻止它改变类型,如果传递给函数的对象是B类,则将其设为B.

2 个答案:

答案 0 :(得分: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>>代替。

答案 1 :(得分: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*,如我的示例所示)。