C++ 继承类工厂
问题描述
我试图了解如何在C++中正确地创建一个继承类工厂。在这个示例中,我使用的是C++ 14。
我做了一个简单的示例来尝试理解这个工作原理:
#include <iostream>
class Animal
{
public:
virtual std::string Sound();
};
class Dog : Animal
{
public:
std::string Sound() {return "Woff!";};
};
class Cat : Animal
{
public:
std::string Sound() {return "Meow!";};
};
class Snake : Animal
{
public:
std::string Sound() {return "Ssss!";};
};
Animal GetAnimal(std::string name)
{
if (name == "Dog")
return Dog();
else if (name == "Cat")
return Cat();
else if (name == "Snake")
return Snake();
return Animal();
}
int main()
{
std::cout << "Sound of a dog: \"" << GetAnimal("Dog").Sound() << "\"\n";
std::cout << "Sound of a cat: \"" << GetAnimal("Cat").Sound() << "\"\n";
std::cout << "Sound of a snake: \"" << GetAnimal("Snake").Sound() << "\"\n";
return 0;
}
在Dog
,Cat
和Snake
都是Animal
的派生类的情况下,我想通过将动物名称作为参数传递给GetAnimal
函数,从中获得每种动物类型的本地实例。
上面的代码在尝试编译GetAnimal
函数中的每一个return
行时会提示以下错误:
E0269 conversion to inaccessible base class "Animal" is not allowed
是否不可能将一个继承类的对象分配给一个继承类的基类类型的变量?在C++中应该如何正确地实现这样的操作呢?
解决方案
您需要使用基类指针或者引用,并且使用public
继承。如果您计划通过基类指针销毁对象,则通常建议将基类的析构函数定义为virtual
。
可以像这样实现:
#include <iostream>
#include <memory>
class Animal {
public:
virtual ~Animal() = default;
virtual std::string Sound() = 0; // needs to be implemented by derived class
};
class Dog : public Animal {
public:
std::string Sound() override { return "Woff!"; };
};
class Cat : public Animal {
public:
std::string Sound() override { return "Meow!"; };
};
class Snake : public Animal {
public:
std::string Sound() override { return "Ssss!"; };
};
std::unique_ptr<Animal> GetAnimal(std::string name) {
if (name == "Dog")
return std::make_unique<Dog>();
else if (name == "Cat")
return std::make_unique<Cat>();
else if (name == "Snake")
return std::make_unique<Snake>();
throw std::runtime_error("Invalid animal");
}
像这样使用:
int main() {
std::cout << "Sound of a dog: \"" << GetAnimal("Dog")->Sound() << "\"\n";
std::cout << "Sound of a cat: \"" << GetAnimal("Cat")->Sound() << "\"\n";
std::cout << "Sound of a snake: \"" << GetAnimal("Snake")->Sound() << "\"\n";
}
输出:
Sound of a dog: "Woff!"
Sound of a cat: "Meow!"
Sound of a snake: "Ssss!"