С++ 11 вектор умного указателя

Вопрос:Предположим, что у нас есть следующие коды. Имеем следующие классы Животное как AbstractClass Собака и птица, которая является подклассом Animal Зоопарк, который держит всех животных _ class Animal { public: Animal(); void HasWings() = 0; }; class Bird : public Animal { public: Bird() : Animal() {} void HasWings() override { return true; } };

Вопрос:

Предположим, что у нас есть следующие коды. Имеем следующие классы

  • Животное как AbstractClass
  • Собака и птица, которая является подклассом Animal
  • Зоопарк, который держит всех животных

_

class Animal { public: Animal(); void HasWings() = 0; }; class Bird : public Animal { public: Bird() : Animal() {} void HasWings() override { return true; } }; class Dog : public Animal { public: Dog() : Animal() {} void HasWings() override { return false; } }; class Zoo { public: Zoo() {} void AddAnimal(Animal* animal) { _animals.push_back(animal); } … std::vector<Animal*> _animals; }; void myTest() { Zoo myZoo; Bird* bird = new Bird(); Dog* dog = new Dog(); myZoo.AddAnimal(bird); myZoo.AddAnimal(dog); for (auto animal : myZoo._animals) { … } … }

Я надеюсь заменить вектор указателей вектором умных указателей. т.е.

std::vector<std::shared_ptr<Animal>> _animals;

Как изменить код для Zoo и myTest?
Мне сложно обновить код, особенно метод “AddAnimal” в классе Zoo

auto bird = std::make_shared<Bird>(); auto dog = std::make_shared<Dog>(); myZoo.AddAnimal(bird); myZoo.AddAnimal(dog);

птица и собака различного типа

Лучший ответ:

Поведение std::shared_ptr очень похоже на поведение исходного указателя относительно операторов * и -> (фактически, операторы разыменования “пересылаются” внутреннему необработанному указателю, хранящемуся в std::shared_ptr). В частности, вы можете использовать std::shared_ptr для базового класса для виртуальной диспетчеризации по иерархии классов. Например, приведенный ниже код выполняет именно то, что предполагается, а именно вызывает соответствующую функцию во время выполнения:

#include <iostream> #include <memory> #include <vector> struct Base { virtual void f() { std::cout << «Base::f()» << std::endl;} virtual ~Base() = default; // to silence -Wall warnings }; struct Derived: Base { void f() override { std::cout << «Derived::f()» << std::endl;} }; int main() { std::vector<std::shared_ptr<Base>> vsp; // access Derived via shared_ptr to Base auto base = std::make_shared<Base>(); auto derived = std::make_shared<Derived>(); vsp.push_back(base); vsp.push_back(derived); for(auto&& elem: vsp) elem->f(); // virtual dispatch }

Итак, большую часть времени достаточно заменить Animal* на std::shared_ptr<Animal>, и код будет работать. С std::unique_ptr ситуация немного сложнее, так как последний тип типа движения (вы не можете его скопировать), поэтому нужно быть более осторожным.

Оцените статью
Добавить комментарий