[英]C++ Instantiating childs of an abstract class with pure virtual functions
我有一个抽象类,例如让它为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();
};
动物.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()
{}
这样,一只猫将是:
猫
class Cat : public Animal
{
public:
Cat();
void Eat() const;
};
目录
Cat::Cat() : Animal()
{}
void Cat::Eat() const
{
// The cat eats.
}
但是此代码不起作用,它在GetAnimal中得到一个错误无效的抽象返回类型'Animal' ,因为Animal是抽象的并且无法实例化,尽管我的API可以确保不会这样做 。
这个问题可能有哪些智能解决方案? 我可以执行Eat Eat函数,并为其提供默认实现,但我不想这样做。
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);
}
}
您说GetAnimal
应该返回一个Animal
对象 ,这不是继承的工作方式,继承主要通过指针进行。 当您尝试返回某个类型的对象时,编译器会隐式地创建一个Animal
对象,但是由于Animal
是一个抽象类,因此不允许这样做。 即使您只将eat()
设为virtual
您仍然会遇到对象切片问题。
您可以使它返回Animal*
并在使用后释放结果:
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);
}
}
呼叫者:
Dog* myDog = GetAnimal(DOG);
//somewhere later when you dont need myDog anymore..(don't forget this!)
delete myDog;
但是,如果您可以访问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);
}
}
呼叫者:
auto dog = GetAnimal(DOG);
//no explicit delete required.
您希望GetAnimal的返回类型是动物的指针,而不是动物本身。 通常,每当您尝试使用多态时,都可以使用指针。
我最好的猜测是,这就是正在发生的事情:您正在实例化Cat。 然后,在您的return语句中,由于您没有返回指针,因此它必须复制您的数据。 由于返回类型为Animal,因此它将尝试调用默认的Animal复制构造函数。 因此,它试图实例化Animal类,这当然是无法完成的。
虚拟成员函数与指针一起使用。 只需将您的API更改为类似的内容:
std::unique_ptr<Animal> Animal::GetAnimal(const int animal)
{
switch(animal)
{
case CAT:
return std::make_unique<Cat>();
(...)
}
}
请注意,我假设您至少在使用C ++ 14
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.