为什么智能指针向量不是指向实现与该接口协变的接口的项目?

Why isn't a vector of smart pointers to an item implementing an interface covariant with that interface?

为什么智能指针向量不与项目实现的接口协变?例如如果我有一个指向狗的指针向量,为什么我不能将它用作指向 iAnimal 的指针向量?

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

struct iAnimal
{
    virtual std::string speak() const = 0;
};

struct iMammal : public iAnimal
{
    virtual std::string speak() const = 0;
    virtual int legs() const = 0;
};


struct Dog : public iMammal
{
    std::string speak() const
    {
        return "WOOF!";
    }
    int legs() const
    {
        return 4;
    }
};


void giveMammals(std::vector<std::shared_ptr<iMammal>> an)
{
    for (const auto x : an)
    {
        x->legs();
    }
}

void giveAnimals(std::vector<std::shared_ptr<iAnimal>> an)
{
    for (const auto x : an)
    {
        x->speak();
    }
}

int main()
{   
    std::vector<std::shared_ptr<Dog>> vec1 = { std::make_shared<Dog>() };
    std::vector<std::shared_ptr<iMammal>> vec= { std::make_shared<Dog>() };
    giveAnimals(vec);
    giveMammals(vec1);
    return 0;
}

原因是您提出的那种代码很容易被利用来做很多令人讨厌的事情。举一个例子,让我们简单地看看,如果这段代码是合法的(它不是),那么如何将 Cat 插入到 Dog 的向量中。

struct Cat : public iMammal {
    std::string speak() const
    {
        return "meow.";
    }
    int legs() const
    {
        return 4;
    }
};

void giveAnimals(std::vector<std::shared_ptr<iAnimal>> & an) {
    //This, on its own, is perfectly legal given the type that `an` is.
    an.emplace_back(std::make_shared<Cat>());

    for (auto const& x : an)
    {
        x->speak();
    }
}

int main() {
    std::vector<std::shared_ptr<Dog>> vec = { std::make_shared<Dog>() };
    giveAnimals(vec);//Uhhhh.......
    for(auto const& dog_ptr : vec) {
        dog_ptr->speak();//These are not all going to bark!
    }
}

std::vector(和其他类似的库结构)禁止这种转换正是为了防止 mistakes/errors 像这样。