简体   繁体   中英

C++ Factory Pattern with Smart Pointers - can't get past “use of deleted function” error

I'm attempting to make a small C++ Factory Pattern example with smart pointers. Here is what I have so far:

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

With GCC 7.3 I get:

error: use of deleted function

With the Microsoft compiler that ships with Visual Studio 2019 I get:

attempting to reference a deleted function

If I comment out these lines the error goes away, so it would seem this is where I'm going wrong:

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

I've looked at very similar examples on Stack Overflow and elsewhere and I can't seem to work out where I'm going wrong. Suggestions please?

--- EDIT ---

After changes per Kit's accepted answer below, here is a complete working copy/pastable example:

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

In your animals.push_back() , you are trying to make a copy of the unique_ptr<> , which is not allowed.

Instead, use:

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

Then the dog and cat will release their pointers and won't delete the objects when the destructors of the smart pointers are called.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM