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