为什么智能指针向量不是指向实现与该接口协变的接口的项目?
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 像这样。
为什么智能指针向量不与项目实现的接口协变?例如如果我有一个指向狗的指针向量,为什么我不能将它用作指向 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 像这样。