首页 > 解决方案 > 带有智能指针的 C++ 工厂模式 - 无法通过“使用已删除函数”错误

问题描述

我正在尝试使用智能指针制作一个小型 C++ 工厂模式示例。这是我到目前为止所拥有的:

// FactorySmart.cpp

#include <iostream>
#include <vector>
#include <memory>

enum AnimalSpecies { dog, cat };

class Animal
{
public:
  virtual void makeSound() = 0;
};

class Dog : public Animal
{
public:
  void makeSound() { std::cout << "woof" << "\n\n"; }
};

class Cat : public Animal
{
public:
  void makeSound() { std::cout << "meow" << "\n\n"; }
};

class AnimalFactory
{
public:
  static std::unique_ptr<Animal> makeAnimal(AnimalSpecies animalSpecies);
};

std::unique_ptr<Animal> AnimalFactory::makeAnimal(AnimalSpecies animalSpecies)
{
  if (animalSpecies == AnimalSpecies::dog)
  {    
    return(std::make_unique<Dog>());   
  }
  else if (animalSpecies == AnimalSpecies::cat)
  {    
    return(std::make_unique<Cat>());    
  }
  else
  {
    std::cout << "error in AnimalFactory::makeAnimal(), animalSpecies = " << animalSpecies << " does not seem to be valid" << "\n\n";
    return(nullptr);
  }
}

int main(void)
{  
  std::vector<std::unique_ptr<Animal>> animals;

  std::unique_ptr<Animal> dog = AnimalFactory::makeAnimal(AnimalSpecies::dog);
  animals.push_back(dog);

  std::unique_ptr<Animal> cat = AnimalFactory::makeAnimal(AnimalSpecies::cat);
  animals.push_back(cat);

  for (auto &animal : animals)
  {
    animal->makeSound();
  }

  return(0);
}

使用 GCC 7.3,我得到:

error: use of deleted function

使用 Visual Studio 2019 附带的 Microsoft 编译器,我得到:

attempting to reference a deleted function

如果我注释掉这些行,错误就会消失,所以这似乎是我出错的地方:

std::unique_ptr<Animal> dog = AnimalFactory::makeAnimal(AnimalSpecies::dog);
animals.push_back(dog);

std::unique_ptr<Animal> cat = AnimalFactory::makeAnimal(AnimalSpecies::cat);
animals.push_back(cat);

我在 Stack Overflow 和其他地方看过非常相似的例子,但我似乎无法弄清楚我哪里出错了。请问有什么建议吗?

- - 编辑 - -

在根据以下 Kit 接受的答案进行更改后,这是一个完整的工作副本/可粘贴示例:

// FactorySmart.cpp

#include <iostream>
#include <vector>
#include <memory>

enum AnimalSpecies { dog, cat };

class Animal
{
public:
  virtual void makeSound() = 0;
};

class Dog : public Animal
{
public:
  void makeSound() { std::cout << "woof" << "\n\n"; }
};

class Cat : public Animal
{
public:
  void makeSound() { std::cout << "meow" << "\n\n"; }
};

class AnimalFactory
{
public:
  static std::unique_ptr<Animal> makeAnimal(AnimalSpecies animalSpecies);
};

std::unique_ptr<Animal> AnimalFactory::makeAnimal(AnimalSpecies animalSpecies)
{
  if (animalSpecies == AnimalSpecies::dog)
  {
    std::unique_ptr<Animal> dog = std::make_unique<Dog>();
    return(dog);
  }
  else if (animalSpecies == AnimalSpecies::cat)
  {
    std::unique_ptr<Animal> cat = std::make_unique<Cat>();
    return(cat);
  }
  else
  {
    std::cout << "error in AnimalFactory::makeAnimal(), animalSpecies = " << animalSpecies << " does not seem to be valid" << "\n\n";
    return(nullptr);
  }  
}

int main(void)
{
  std::vector<std::unique_ptr<Animal>> animals;

  std::unique_ptr<Animal> dog = AnimalFactory::makeAnimal(AnimalSpecies::dog);
  animals.push_back(std::move(dog));

  std::unique_ptr<Animal> cat = AnimalFactory::makeAnimal(AnimalSpecies::cat);
  animals.push_back(std::move(cat));

  for (auto &animal : animals)
  {
    animal->makeSound();
  }  

  return(0);
}

标签: c++smart-pointersfactory-pattern

解决方案


在您的animals.push_back()中,您试图制作 的副本unique_ptr<>,这是不允许的。

相反,使用:

std::unique_ptr<Animal> dog = AnimalFactory::makeAnimal(AnimalSpecies::dog);
animals.push_back(std::move(dog));

std::unique_ptr<Animal> cat = AnimalFactory::makeAnimal(AnimalSpecies::cat);
animals.push_back(std::move(cat));

然后dogandcat将释放它们的指针,并且在调用智能指针的析构函数时不会删除对象。


推荐阅读