[英]Iterate through a vector of shared_ptr
我有两个类(羊和狼)源自一个(动物)。 我创建了一个这样的共享指针向量:
std::vector<std::shared_ptr<animal>> animals;
for (int i = 0; i < n_sheep; i++) {
auto my_sheep = std::make_shared<sheep>();
animals.push_back(std::move(my_sheep));
}
for (int i = 0; i < n_wolf; i++) {
auto my_wolf = std::make_shared<wolf>();
animals.push_back(std::move(my_wolf));
}
遍历此向量并了解这些 smart_ptr 之间区别的最佳方法是什么?
像这样的东西:
for (int i = 0; i < animals.size(); i++) {
if (animals[i] == sheep)
//TODO
if (animals[i] == wolf)
//TODO
谢谢你们。
“最好的”取决于几件事。 例如,谁控制 class Animal 的定义?
我真的很喜欢做类似的事情:
class Animal
{
public:
virtual std::string what() = 0;
};
class Wolf : public Animal
{
public:
virtual std::string what() { return "wolf"; }
};
class Sheep : public Animal
{
public:
virtual std::string what() { return "sheep"; }
};
您还可以定义一个枚举来摆脱比较字符串的需要,但是当然,这意味着您将失去在不编辑该枚举的情况下添加更多动物的能力。
如果您无法更改Animal
,您可以执行以下操作:
if( typeid(*animals[i]) == typeid(Wolf) )
{
// do wolfy things
}
else if( typeid(*animals[i]) == typeid(Sheep) )
{
// do sheepish things
}
您可以使用dynamic_pointer_cast
将一个衍生 class 与另一个衍生。 这可能不是最好的方法,但即使您无法向基础添加新的虚拟方法,它也可以工作。
for (auto animal: animals){
auto p = std::dynamic_pointer_cast<wolf>(animal);
if(p) std::cout << "wolf"; // p will be null if it is not wolf
else std::cout << "sheep"; // if you have only two animals,
// otherwise you need to cast to sheep
// to check if it is actually sheep
}
作为@v010dya 方法的一种变体(假设您可以自由修改Animal),我会(如前所述)使用枚举。 如果您选择十六进制值,则可以使用位运算符,这使得比较更简单(尽管依赖于隐式转换为 int)。
但是,我会将此逻辑拆分为“关系”class。 问题是您真的不想用派生类的知识污染 Animal,但您确实需要有一种方法让不同的派生类进行交互。
在这里,我使用 Menagarie 作为 class 来控制不同动物之间的关系。 这样一来,Wolf 就不需要知道关于 Sheep 的任何事情,只需要知道它是一种可以吃的动物。 您可以将此模式用于不同类型动物之间的其他交互。
#include <iostream>
//Fwd definition of Animal
class Animal;
//This class controls the relationships between animals
class Menagerie
{
public:
enum Type { NONE = 0x00, SHEEP = 0x01, GOAT = 0x02, WOLF = 0x04, LION = 0x08 };
//Defines the food chain
static bool canBeEatenBy(const Animal* pLunch, const Animal* pDiner);
};
class Animal
{
public:
virtual Menagerie::Type type() const = 0;
virtual void DoSomething() = 0;
virtual ~Animal() {}
};
class Sheep : public Animal
{
public:
Menagerie::Type type() const override { return Menagerie::SHEEP; }
void DoSomething() override
{
//Do Sheep-specific things
}
};
class Wolf : public Animal
{
public:
Menagerie::Type type() const override { return Menagerie::WOLF; }
void DoSomething() override
{
//Do Wolf-specific things
}
};
//This defines the logic of who-eats-who
//Can be moved to implementation file, so you can
//change the logic in one place with minimal recompilation
bool Menagerie::canBeEatenBy(const Animal* pLunch, const Animal* pDiner)
{
switch (pLunch->type())
{
case SHEEP:
return pDiner->type() & (WOLF | LION);
case GOAT:
return pDiner->type() & (WOLF | LION);
case WOLF:
return pDiner->type() & LION;
case LION:
return false;
default:
return false;
}
}
int main()
{
Wolf w;
Sheep s;
if (Menagerie::canBeEatenBy(&s, &w))
{
std::cout << "Lunchtime for Wolf!\n";
}
if (Menagerie::canBeEatenBy(&w, &s))
{
std::cout << "Lunchtime for Sheep!\n";
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.