2017-02-15 115 views
1

修改了一些旧的代码,我手动处理了一个向量指针的生命期到抽象基类(ABC)的具体实例。How /是否可以有一个向量<unique_ptr <ABC>>?

所以矢量的主人有哪些手动经历,并删除了矢量内容的虚拟析构函数等

由于矢量的所有者拥有它的元素,这让很多的意义,这种改变unique_ptr的向量。

不幸的是,这似乎是不可能的?因为vector<unique_ptr<type>>必须能够有一个静态的析构函数用于type但由于在这种情况下,类型是ABC,这是不可用,因此vector将无法​​编译...

还是我失去了一些东西?

如:

struct ABC 
{ 
    ABC() = default; 
    virtual ~ABC() { } // need a vtable entry so that concrete subclasses will be deleted through the base dtor 

    virtual std::unique_ptr<ABC> Clone() = 0; 
    virtual void Foo() = 0; 

    std::vector<std::unique_ptr<ABC>> elements; 
}; 

EDIT2:这里是一个失败的完整的例子:

#include <iostream> 
#include <memory> 
#include <vector> 

struct ABC 
{ 
    virtual ~ABC() { } // need a vtable entry so that concrete subclasses will be deleted through the base dtor 

    virtual std::unique_ptr<ABC> Clone() = 0; 
    virtual void Foo() = 0; 

    std::vector<std::unique_ptr<ABC>> elements; 
}; 

struct Child : ABC 
{ 
    std::unique_ptr<ABC> Clone() override { return std::make_unique<Child>(*this); } 
    void Foo() override { }; 
}; 

struct Derived : Child 
{ 
    std::unique_ptr<ABC> Clone() override { return std::make_unique<Derived>(*this); } 
}; 

int main() 
{ 
    std::unique_ptr<ABC> x; 
    std::unique_ptr<ABC> c = std::make_unique<Child>(); 

    std::vector<std::unique_ptr<ABC>> elements; 
    elements.emplace_back(std::make_unique<Derived>()); 
    return 0; 
} 
+0

不知道关于其他人,但如果你从问题的示例代码使用相同的名字它使你问很多更清晰。那就是说,你得到的错误是什么?你的示例代码为我编译。 – NathanOliver

+0

难道你只是转发申报基地?在你定义它之前? –

+0

我从VS 2015 Upd 3中得到了一英里长的消息,这基本上是由于在Base中删除ctor而导致实例化缺省填充“元素”的元素失败(大概是因为它是ABC) – Mordachai

回答

4

当您尝试复制的Base实例或Base派生类型的实例出现的错误。默认的拷贝构造函数将尝试拷贝Base::elements,它试图将它的每个元素拷贝到新的vector中。由于这些元素是unique_ptr<Base>此副本是不允许的。

这个例子重现问题:

#include <memory> 
#include <vector> 

struct Base 
{ 
    using PBase = std::unique_ptr<Base>; 
    using VBase = std::vector<PBase>; 

    VBase elements; 
}; 

int main() 
{ 
    Base x; 
    auto y = x; // This line causes the error 

    return 0; 
} 

您可能需要实现自己的拷贝构造函数和拷贝赋值运算符,或者删除这些功能禁止复制。如果浅拷贝适用于您的应用程序,则可以使用shared_ptr来代替。

+0

谢谢。我只是没有看到明显的。多谢。 – Mordachai

0

为了完整起见,这里是我一直在做的事情:

class ABC 
{ 
public: 
    ABC() = default; 
    ABC(const ABC & rhs) 
    { 
     // manually clone our elements 
     elements.reserve(rhs.elements.size()); 
     for (const auto & e : rhs.elements) 
      elements.emplace_back(e->Clone()); 
    } 
    ABC & operator = (const ABC &) = delete; 

    virtual ~ABC() { } // need a vtable entry so that concrete subclasses will be deleted through the base dtor 

    virtual std::unique_ptr<ABC> Clone() = 0; 
    virtual void Foo() = 0; 

    std::vector<std::unique_ptr<ABC>> elements; 
}; 
相关问题