我想做以下事情:
virtual void Aircraft::getImage(GenericImage&)=0;
void Drone::getImage(Image&);
,其中
Image
是GenericImage
的子类
Drone
是Aircraft
的子类。
如果没有编译器抱怨getImage(any subclass of genericImage&)
和genericImage
不是同一个东西,我怎么能要求Drone类有Image
方法?我希望最终用户/ dev能够使用自己的图像格式定义自己的无人机类,该格式扩展genericImage
,但无论他们创建什么,他们必须提供从无人机获取图像的功能。
答案 0 :(得分:1)
不要取出参数,只需返回图像即可。返回类型允许协变。这意味着,只要Image
实际上公开来自GenericImage
,就可以了:
virtual GenericImage& Aircraft::getImage() = 0;
virtual Image& Drone::getImage();
答案 1 :(得分:0)
不可能以这种方式更改参数,也不应该因为它通常违反Liskov替换原则(LSP):Aircraft::getImage
可以接受任何GenericImage
,包括GenericImage
的任意子类。子类必须符合该接口,因此还必须接受任何GenericImage
。但是,您明确要指定它只接受特定子类型Image
。
请注意,返回类型的情况不同,因为它们表示函数生成而不是函数接受的内容(您可以假设您的getImage
也产生了,但是C ++不知道out参数的概念,并且您确实必须将现有对象传递给getImage
以便用图像数据填充它。因为对于返回类型,转到派生类型并不违反LSP,C ++确实允许它(该特征称为协变返回类型)。因此,解决方案是在函数内部分配图像对象并返回(最好使用指针 - 不幸的是,智能指针不适用于协变返回类型 - 以指示发生的分配)。也就是说,你的函数会读取
class Aircraft
{
virtual GenericImage* getImage() = 0;
};
class Drone: public Aircraft
{
virtual Image* getImate() { return new Image(); }
};
然而,最有可能你只会使用基类接口,因此我更喜欢在界面中使用GenericImage
,而是利用智能指针:
class Aircraft
{
virtual std::unique_ptr<GenericImage> getImage() = 0;
};
class Drone: public Aircraft
{
virtual std::unique_ptr<GenericImage> getImate() { return new Image(); }
};