多态在没有指针/引用的情况下在C++中工作吗?

lez*_*lon 7 c++ object-slicing

可能重复:
虚函数对象切片

让我们考虑一下:

#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
}
Run Code Online (Sandbox Code Playgroud)

哪个功能会被调用?如果不存在切片,基本上可以使用不带指针的多态性吗?

Man*_*Way 13

不,没有指针就不可能.

由于您创建了一个对象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();
}
Run Code Online (Sandbox Code Playgroud)

输出将是:

Hello A
Run Code Online (Sandbox Code Playgroud)


bet*_*ido 6

问题是在你的例子中实际上有切片.使用push_back在某种程度上相当于:

A array[N];
array[last++] = B();
Run Code Online (Sandbox Code Playgroud)

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

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


Mik*_*our 5

多态在没有指针/引用的情况下在C++中工作吗?

是的,不是.

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

静态多态,使用模板,与对象完美协作,但解决了不同类别的问题.您的示例需要动态多态,以根据对象的运行时类型选择行为.

哪个功能会被调用?

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

如果不存在切片,基本上可以使用不带指针的多态性吗?

从派生类对象创建基类对象时,始终存在切片.这就是切片的定义.


Luc*_*ore 5

多态在没有指针/引用的情况下在C++中工作吗?

是.请参阅静态多态.

在你的情况下,将调用基函数,但说多态不起作用是错误的.多态性保证有效,只是你没有利用它.你拥有的基本上是A对象的集合.