我可以在C++ 11中使用具有值语义的多态容器吗?

Joh*_*ing 6 c++ stl c++11

这是一个相关帖子的续集,它询问了永恒的问题:

我可以在C++中使用具有值语义的多态容器吗?

问题稍有不正确.应该更像是:

我可以使用按值存储的基类型的STL容器,其中元素表现出多态行为吗?

如果你用C++问这个问题,答案是"不".在某些时候,您将切片按值存储的对象.

现在我再次提出这个问题,但严格来说是C++ 11.通过对语言和标准库的更改,现在可以在STL容器中按值存储多态对象吗?

我很清楚在容器中存储智能指针到基类的可能性 - 这不是我正在寻找的,因为我试图在不使用的情况下在堆栈上构造对象new.

考虑你是否(从链接的帖子)作为基本的C++示例:

#include <iostream>

using namespace std;

class Parent
{
    public:
        Parent() : parent_mem(1) {}
        virtual void write() { cout << "Parent: " << parent_mem << endl; }
        int parent_mem;
};

class Child : public Parent
{
    public:
        Child() : child_mem(2) { parent_mem = 2; }
        void write() { cout << "Child: " << parent_mem << ", " << child_mem << endl; }

        int child_mem;
};

int main(int, char**)
{
    // I can have a polymorphic container with pointer semantics
    vector<Parent*> pointerVec;

    pointerVec.push_back(new Parent());
    pointerVec.push_back(new Child());

    pointerVec[0]->write();     
    pointerVec[1]->write();     

    // Output:
    //
    // Parent: 1
    // Child: 2, 2

    // But I can't do it with value semantics

    vector<Parent> valueVec;

    valueVec.push_back(Parent());
    valueVec.push_back(Child());        // gets turned into a Parent object :(

    valueVec[0].write();        
    valueVec[1].write();        

    // Output:
    // 
    // Parent: 1
    // Parent: 2

}
Run Code Online (Sandbox Code Playgroud)

Jam*_*lis 8

你当然不能有一个多态数组(或vector).数组元素在内存中连续存储的要求从根本上与不同派生类类型可能具有不同大小的事实不兼容.

没有标准库容器允许在单个容器中存储不同派生类类型的对象.


Oli*_*rth 4

只是为了好玩,根据 James 对基于模板的系统的评论,我想出了这个类似 Vector 的实现。它缺少很多功能,并且可能有问题,但它是一个开始!

#include <iostream>
#include <vector>
#include <boost/shared_ptr.hpp>

template <typename T>
class Vector
{
public:
    T &operator[] (int i) const { return p[i]->get(); }
    template <typename D>
    void push_back(D &x) { p.push_back(ptr_t(new DerivedNode<D>(x))); }

private:
    class Node
    {
    public:
        virtual T &get() = 0;
    };

    template <typename D>
    class DerivedNode : public Node
    {
    public:
        DerivedNode(D &x) : x(x) {}
        virtual D &get() { return x; }
    private:
        D x;
    };

    typedef boost::shared_ptr<Node> ptr_t;
    std::vector<ptr_t> p;
};

///////////////////////////////////////

class Parent
{
    public:
        Parent() : parent_mem(1) {}
        virtual void write() const { std::cout << "Parent: " << parent_mem << std::endl; }
        int parent_mem;
};

class Child : public Parent
{
    public:
        Child() : child_mem(2) { parent_mem = 2; }
        void write() const { std::cout << "Child: " << parent_mem << ", " << child_mem << std::endl; }

        int child_mem;
};


int main()
{
    Vector<Parent> v;

    v.push_back(Parent());
    v.push_back(Child());

    v[0].write();
    v[1].write();
}
Run Code Online (Sandbox Code Playgroud)

  • 你正在重新发明轮子:“boost::ptr_vector”做得更好(不涉及“shared_ptr”)。另请注意,基本要求不是“新的”。对于“new”来说,这是微不足道的(并且有库)。 (2认同)