c ++对象参数:多态,值语义,对象生命周期?

Use*_*ser 3 c++ parameters abstract-class object-lifetime dynamic-allocation

当我从C#转换到C++时,我得到了很多建议,尽可能使用值语义.几乎可以肯定的是,如果我在任何地方发布带有指针的问题,并建议它应该是一个值.我开始看到了光,我在代码中找到了很多地方,我可以用堆栈分配的变量(通常是引用)替换动态分配和指针.所以我认为我掌握了使用堆栈分配的对象,并且当调用者中的对象生命周期比被调用者更长时,将它们作为引用传递给其他函数.

但是,当被调用者获得所有权时,我有一个关于按值传递对象的问题.请看以下示例:

class Zoo
{
  void AddAnimal(Animal animal);
  std::list<Animal> animals_;
}
Run Code Online (Sandbox Code Playgroud)

通常从灵活性和单元测试的角度来看,我希望Animal成为一个接口(C++中的抽象类),这样我就可以轻松地发送任意动物并通过模拟实现来模拟它.

在指针实现中,客户端代码将调用它:

Animal animal = new Lion("Bob");
myZoo.AddAnimal(animal);
Run Code Online (Sandbox Code Playgroud)

这里的客户端代码并不真正需要动物对象.它只是暂时构建它以传递给方法.所以在这种情况下,没有共享语义.所以它似乎是价值语义的一个好例子.但是,我的理解是你不能使用Animal作为值传递的参数,因为它是一个抽象类.

我的大多数不采用原始类型的成员函数都采用抽象类参数.那么处理这个问题的C++方法是什么?(那你是如何使用值语义编写C++接口的呢?)

Ker*_* SB 7

您的方案的典型解决方案将涉及资源管理处理程序对象,您可以通过值传递该对象.热门候选人shared_ptrunique_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
}
Run Code Online (Sandbox Code Playgroud)

如果可行,你也可以定义AnimalPtrstd::unique_ptr<Animal>,但是你必须说addAnimal(std::move(a));.这是更严格的限制(因为在任何给定时间只有一个物体处理动物),但也更轻.