7

可能重复:
虚拟功能对象切片

让我们考虑一下:

#include <vector>
#include <iostream>
using namespace std;

struct A {
    virtual void do_it() { cout << "A" << endl; } 
};

struct B : public A {
    virtual void do_it()  { cout << "B" << endl; } 
};

int main() {
    vector<A> v;
    v.push_back(B());
    v[0].do_it(); // output is A
}

哪个函数会被调用?如果不存在切片,基本上是否可以在没有指针的情况下使用多态性?

4

5 回答 5

15

不,没有指针是不可能的。

由于您创建了一个对象B并将其推送到包含 的向量A,因此它将被复制(发送到 的复制构造函数A),并且 的实例A将被添加到向量中。即对象将被切片。

鉴于此代码:

struct A {
        virtual void d() { 
            std::cout << "Hello A" << std::endl; 
        } 
};

struct B : public A {
        virtual void d() { 
            std::cout << "Hello B" << std::endl; 
        } 
};

int main() {
        std::vector<A> v;
        v.push_back(B());
        v[0].d();
}

输出将是:

Hello A
于 2012-07-26T14:07:13.737 回答
6

问题是在你的例子中实际上有slicing。使用push_back在某种程度上等同于:

A array[N];
array[last++] = B();

第二行是切片的位置,因为数组中的每个位置都可以保存 type 中的对象,A但不能保存 type 中的对象B

您可以使用指针来解决这个问题,定义vstd::vector<A*> v. 可能更好的是,您可以使用智能指针(C++11中的指针或Boost中的指针)。

于 2012-07-26T14:07:02.913 回答
5

多态性是否在没有指针/引用的 C++ 中工作?

是和不是。

当指针或引用的静态类型可能与它所引用的对象的动态类型不同时,动态多态性在 C++ 中起作用,并且基于动态类型选择行为。这需要指针或引用,因为对象本身只有一种类型。

使用模板的静态多态性与对象完美配合,但解决了另一类问题。您的示例需要动态多态性,以根据对象的运行时类型选择行为。

哪个函数会被调用?

该向量包含类型的对象A,因此A::do_it()将被调用。该对象不知道它是通过切片类型的对象创建的B

如果不存在切片,基本上是否可以在没有指针的情况下使用多态性?

当您从派生类对象创建基类对象时,总是存在切片。这就是切片的定义。

于 2012-07-26T14:26:22.957 回答
4

多态性是否在没有指针/引用的 C++ 中工作?

是的。请参阅静态多态性

在您的情况下,将调用基本函数,但是说多态不起作用是错误的。多态性保证可以工作,只是你没有利用它。你所拥有的基本上是一个 A 对象的集合。

于 2012-07-26T14:26:40.893 回答
0

这不起作用,因为 sizeof(parent) 并不总是等于 sizeof(child)

于 2012-07-26T14:01:32.250 回答