web-dev-qa-db-ja.com

スマートポインタのC ++ 11ベクトル

次のコードがあるとします。以下のクラスがあります

  • AbstractClassとしての動物
  • 動物のサブクラスである犬と鳥
  • すべての動物を飼育する動物園

_

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のコードをどのように変更しますか?コード、特にZooクラスのメソッド「AddAnimal」の更新が難しいと感じています

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

鳥と犬はタイプが違います

9
user2434918

std::shared_ptrの動作は、*および->演算子に関して、rawポインターの動作と非常に似ています(実際、逆参照演算子は、格納されている内部rawポインターに「転送」されます)。 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は移動専用タイプ(コピーできない)であるため、状況は少し複雑になります。したがって、より注意する必要があります。

10
vsoftco