Шаблон фабрики C ++ с умными указателями - не может пройти мимо ошибки "использования удаленной функции" - PullRequest
1 голос
/ 16 июня 2019

Я пытаюсь создать небольшой пример фабричного шаблона 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

С компилятором Microsoft, который поставляется с Visual Studio 2019, я получаю:

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);

Я смотрел на очень похожие примеры переполнения стека и в других местах, и я не могу понять, где я ошибаюсь. Предложения, пожалуйста?

--- РЕДАКТИРОВАТЬ ---

После изменений в соответствии с принятым ответом 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);
}

1 Ответ

2 голосов
/ 16 июня 2019

В вашем 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));

Затем dog и cat будут освобождать свои указатели и не будут удалять объекты при вызове деструкторов умных указателей.

...