【问题标题】:Instantiate unique_ptr to derived class from vector of base class where derived class has been stored从已存储派生类的基类的向量将 unique_ptr 实例化为派生类
【发布时间】:2019-05-13 16:16:03
【问题描述】:

考虑以下代码:

struct  Fruit
{
   Fruit() {}
   virtual ~Fruit() {}       
   std::string name;
};

struct Banana : public Fruit
{
   std::string color;
};

struct Pineapple : public Fruit
{
   int weight;
};

这是我的 main() :

int main()
{
    std::vector<std::unique_ptr<Fruit>> product;
    product.push_back(std::unique_ptr<Banana>(new Banana)); //product[0] is a Banana
    product.emplace_back(new Pineapple);

    // I need to acess the "color" member of product[0]
    std::unique_ptr<Banana> b = std::move(product[0]); // this doesn't work, why?
    auto c = b->color;
}

product[0] 中,我将一个 unique_ptr 存储到 Banana,为什么我不能将它分配给一个香蕉 unique_ptr ?

【问题讨论】:

  • 编译器不知道product[0] 指向Banana 而不是其他Fruit。如果您确定这一点,您可以通过强制转换告诉编译器。例如std::unique_ptr&lt;Banana&gt; b{static_cast&lt;Banana*&gt;(product[0].release())};
  • 使用 release() 我的产品[0] 丢失了。我不希望这种情况发生,因为我打算再次使用它。还有其他方法吗?
  • 如果要编译它,std::unique_ptr&lt;Banana&gt; b = std::move(product[0]); 也会同样丢失,所以我认为这就是你想要的。如果您不是要从向量中获取所有权,请将其设为 auto b = static_cast&lt;Banana*&gt;(product[0].get());

标签: c++ oop c++11 inheritance unique-ptr


【解决方案1】:

你不想所有权转移,所以只转换指针:

auto& banana = dynamic_cast<Banana&>(*product[0]);
auto c = b->color;

dynamic_cast 可能会被 static_cast 替换,如果您确定 Fruit 确实是 Banana。 如果您错了,static_cast 将导致 UB,而您可以使用 dynamic_cast 检查有效性(强制转换为引用或使用强制转换为指针的空指针除外)。

【讨论】:

    【解决方案2】:

    您需要显式转换,因为第一个产品可以是任何水果...编译器不知道该水果是香蕉还是菠萝。

    正如@IgorTandetnik 所说,您可以这样做:

    std::unique_ptr<Banana> b{static_cast<Banana*>(product[0].release())};
    

    其中使用了release(),以及static_cast

    Live demo

    注意:你不能回退到对 b 使用 auto,因为编译器会选择 struct Fruit 作为类型,以便为任何子类做好准备。

    【讨论】:

    • 使用 release() 我的产品[0] 永远丢失了。我不希望这种情况发生,因为我打算再次使用它。还有其他方法吗?
    • @Gaetan 应该只有 one unique_ptr 指向一个给定的对象。如果它是本地的std::unique_ptr&lt;Banana&gt; b,那么它不能是productstd::unique_ptr&lt;Fruit&gt; 元素。也许你只想要一个Banana * b
    • 哦,是的,使用 `Banana* b´ 一切正常。谢谢。因此,如果不将现有的 unique_ptr 设置为 nullptr,就永远不能用现有的 unique_ptr 实例化 unique_ptr,对吧?
    • @Gaetan unique_ptr唯一的,即它不能共享所有权。这就是为什么不能复制它的原因,所以是的。
    猜你喜欢
    • 2021-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-23
    • 1970-01-01
    • 2016-03-30
    • 2014-09-29
    • 2020-08-30
    相关资源
    最近更新 更多