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
}

我的问题是,为什么从列表中取出对象是 A 以及如果我传递给函数的对象属于 B 类,如何防止它更改类型并将其变为 B。

4

2 回答 2

5

的类型Asstd::list<A>。它存储A对象。如果你试图把一个B物体放进去,它会被切片,你只会得到A它的一部分。每当您从列表中获取一个元素时,它就是一个A对象,因此您调用它的任何函数都将是A.

在 C++ 中有两种获得多态行为的方法:指针或引用。例如,您可以A在列表中存储指向的指针:

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

当然,最好将其包装在智能指针中。

要使用引用,您可以使用 astd::list<std::reference_wrapper<A>>代替。

于 2013-04-03T22:59:23.390 回答
3

这是对象切片问题的一个很好的例子,其中的实例B被切片到实例的实例,A因此丢失了特定的内容B(参见什么是对象切片?)。

在使用对象列表时,您不会实现这种运行时多态性。您可以改用指针列表:

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

甚至更好:再次利用 RAII 并使用智能指针而不是裸指针(即A*如我的示例中所示)。

于 2013-04-03T22:59:43.230 回答