当我从 C# 过渡到 C++ 时,我收到了很多关于尽可能使用值语义的建议。几乎可以保证,如果我在任何地方发布带有指针的问题,就会有人出现并建议它应该是一个值。我开始看到曙光,我在代码中发现了很多地方可以用堆栈分配的变量(通常是引用)替换动态分配和指针。因此,我认为当调用者中的对象生存期比被调用者中的对象生存期长时,我可以掌握使用堆栈分配的对象并将它们作为引用传递给其他函数。
但是,当被调用者取得所有权时,我有一个关于按值传递对象的问题。举个例子:
class Zoo
{
void AddAnimal(Animal animal);
std::list<Animal> animals_;
}
通常,从灵活性和单元测试的角度来看,我希望 Animal 成为一个接口(C++ 中的抽象类),这样我就可以轻松发送任意动物并使用模拟实现来模拟它。
在指针实现中,客户端代码将这样调用:
Animal animal = new Lion("Bob");
myZoo.AddAnimal(animal);
这里客户端代码并不真正需要动物对象。它只是临时构建它以传递给该方法。所以在这种情况下,不存在共享语义。所以这似乎是值语义的一个很好的例子。但是,我的理解是,您不能使用 Animal 作为按值传递的参数,因为它是一个抽象类。
我的大多数不采用基本类型的成员函数都采用抽象类参数。那么C++的处理这个问题的方法是什么呢? (这就是如何使用值语义对 C++ 接口进行编程?)
您的场景的典型解决方案将涉及一个资源管理处理程序对象,您可以使用该对象do按值传递。热门候选人是shared_ptr
and unique_ptr
:
#include <list>
#include <memory>
#include "all_zoo_animals.h" // yours
typedef std::shared_ptr<Animal> AnimalPtr; // see note
typedef std::list<AnimalPtr> AnimalCollection;
AnimalCollection zoo;
void addAnimal(AnimalPtr a)
{
zoo.push_back(a);
}
int main()
{
AnimalPtr a = AnimalPtr(new Penguin);
a.feed(fish);
addAnimal(a); // from local variable, see note
addAnimal(AnimalPtr(new Puffin)); // from temporary
}
如果可行的话,你也可以定义AnimalPtr
as std::unique_ptr<Animal>
,但是你必须说addAnimal(std::move(a));
。这更具限制性(因为在任何给定时间只有一个物体可以处理动物),但重量也更轻。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)