Создайте экземпляр unique_ptr для производного класса из вектора базового класса, в котором был сохранен производный класс - PullRequest
0 голосов
/ 12 декабря 2018

Рассмотрим следующий фрагмент кода:

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?

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

Вы не хотите передачи права собственности, поэтому приведите только указатель:

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

dynamic_cast можно заменить на static_cast, если вы действительно уверены, что Fruit действительно Banana.В случае, если вы ошибаетесь, static_cast приведет к UB, тогда как вы можете проверить достоверность с помощью dynamic_cast (исключение - приведение к ссылке или нулевой указатель с приведением к указателю).

0 голосов
/ 12 декабря 2018

Вам нужно явно разыграть, поскольку первым продуктом может быть любой фрукт ... Компилятор не знает, является ли этот фрукт бананом или ананасом.

Как сказал @IgorTandetnik, вы можете сделать:

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

, где используется release(), а также static_cast.

Live demo

Примечание. Нельзя использовать auto для b, поскольку компилятор выберет struct Fruit в качестве типа, чтобы подготовиться к любому подклассу.

...