San*_*Gil 1 c++ polymorphism abstract-class return-by-value
我有一个抽象类,例如Animal。Animal 有一个纯虚函数eat,如果每个动物不想挨饿,就必须实现它。我确保只能通过这种方式实例化 Animal 的孩子:
动物.hpp
class Animal
{
public:
enum eAnimal{
CAT=0,
DOG=1,
BIRD=2
};
// Instantiates the desired animal.
static Animal GetAnimal(const int animal);
virtual void Eat() const = 0;
protected:
Animal();
};
Run Code Online (Sandbox Code Playgroud)
动物.cpp
Animal Animal::GetAnimal(const int animal)
{
switch(animal)
{
case CAT:
return Cat();
case DOG:
return Dog();
case BIRD:
return Bird();
default:
cerr << "Animal not recognized." << endl;
exit(-1);
}
}
Animal::Animal()
{}
Run Code Online (Sandbox Code Playgroud)
有了这个,猫将是:
猫.hpp
class Cat : public Animal
{
public:
Cat();
void Eat() const;
};
Run Code Online (Sandbox Code Playgroud)
目录
Cat::Cat() : Animal()
{}
void Cat::Eat() const
{
// The cat eats.
}
Run Code Online (Sandbox Code Playgroud)
但是,此代码不起作用,它在GetAnimal 中收到错误无效抽象返回类型“Animal”,因为 Animal 是抽象的并且无法实例化,尽管我的 API 确保它不会。
这个问题可能有哪些智能解决方案?我可以做函数Eat not pure 并给它一个默认实现,但我不想这样做。
Animal Animal::GetAnimal(const int animal)
{
switch(animal)
{
case CAT:
return Cat();
case DOG:
return Dog();
case BIRD:
return Bird();
default:
cerr << "Animal not recognized." << endl;
exit(-1);
}
}
Run Code Online (Sandbox Code Playgroud)
你说GetAnimal应该返回一个Animal 对象,这不是继承的工作方式,继承主要通过指针工作。当您尝试返回某个类型的对象时,编译器必须隐式地创建一个Animal对象,但不允许这样做,因为它Animal是一个抽象类。即使你做eat()只有virtual你仍旧有对象切割问题。
你可以让它返回 aAnimal*并在你使用它后释放结果:
Animal* Animal::GetAnimal(const int animal)
{
switch(animal)
{
case CAT:
return new Cat();
case DOG:
return new Dog();
case BIRD:
return new Bird();
default:
cerr << "Animal not recognized." << endl;
exit(-1);
}
}
Run Code Online (Sandbox Code Playgroud)
呼叫者:
Dog* myDog = GetAnimal(DOG);
//somewhere later when you dont need myDog anymore..(don't forget this!)
delete myDog;
Run Code Online (Sandbox Code Playgroud)
但是如果您可以访问 C++11 或更高版本,我建议使用智能指针而不是原始指针来让指针自行释放:
#include <memory>
std::unique_ptr<Animal> Animal::GetAnimal(const int animal)
{
switch(animal)
{
case CAT:
return std::make_unique<Cat>();
case DOG:
return std::make_unique<Dog>();
case BIRD:
return std::make_unique<Bird>();
default:
cerr << "Animal not recognized." << endl;
exit(-1);
}
}
Run Code Online (Sandbox Code Playgroud)
呼叫者:
auto dog = GetAnimal(DOG);
//no explicit delete required.
Run Code Online (Sandbox Code Playgroud)