在研究这个例子之后我还有一个问题:C++ ecosystem simulator (inheritance)。
想象一下,我有一个类似的例子,我希望使用std::unique_ptr
。有没有办法在下面的示例中进行动态转换,而不必使用.get()
上的std::unique_ptr
来获取原始指针?我在代码中添加了两个变体:一个(can_eat_1
)以旧式方式执行,另一个我在.get()
中有一个dynamic_cast
,我想知道它是否可以被删除并替换为更优雅的方法(can_eat_2
):
#include <iostream>
#include <memory>
struct Animal
{
virtual ~Animal() {};
};
struct Carnivore : public Animal {};
struct Herbivore : public Animal {};
struct Wolf : public Carnivore {};
struct Rabbit : public Herbivore {};
bool can_eat_1(Animal* predator, Animal* prey)
{
return ( dynamic_cast<Carnivore*>(predator) && dynamic_cast<Herbivore*>(prey) );
}
bool can_eat_2(std::unique_ptr<Animal>& predator, std::unique_ptr<Animal>& prey)
{
return ( dynamic_cast<Carnivore*>(predator.get()) && dynamic_cast<Herbivore*>(prey.get()) );
}
int main()
{
std::unique_ptr<Animal> wolf (new Wolf );
std::unique_ptr<Animal> rabbit(new Rabbit);
std::cout << "Option 1: pass raw pointers:" << std::endl;
std::cout << "Wolf eats rabbit = " << can_eat_1(wolf.get(), rabbit.get()) << std::endl;
std::cout << "Rabbit eats wolf = " << can_eat_1(rabbit.get(), wolf.get()) << std::endl;
std::cout << "Option 2: pass unique_ptr:" << std::endl;
std::cout << "Wolf eats rabbit = " << can_eat_2(wolf, rabbit) << std::endl;
std::cout << "Rabbit eats wolf = " << can_eat_2(rabbit, wolf) << std::endl;
return 0;
}
答案 0 :(得分:2)
函数签名中智能指针的指导原则是,当且仅当函数关注智能指针本身时,它们应该出现在那里,也就是说,该函数涉及对象生存期管理。
std::unique_ptr<Foo> f(); // Factory (gives an object to the caller)
void f(std::unique_ptr<Foo> &p); // Factory via output parameter
void f(std::unique_ptr<Foo> p); // Sink (takes an object from the caller)
在您的情况下,该功能会检查您动物的属性。它根本不关心他们的一生。因此,智能指针不应出现在其签名中。
void f(Foo const &p); // Observe a Foo
void f(Foo const *p); // Observe a Foo
您使用的指针或参考中的哪一个是品味问题,但这里通常的选择是参考。
can_eat_3(*rabbit, *wolf);
答案 1 :(得分:0)
你可以通过参考试试这个:
bool can_eat_3(Animal const& predator, Animal const& prey)
{
return
dynamic_cast<Carnivore*>(&predator)
&&
dynamic_cast<Herbivore*>(&prey);
}
并通过以下方式调用:
can_eat_3(*wolf, *rabbit);
如果您取消引用并获取地址,您也可以使用can_eat_1:
can_eat_1(&*wolf, &*rabbit);
但是,我并不认为这更优雅......