2012-01-10 4 views
0

Я хочу сделать что-то вроде следующего:дочерний объект в качестве параметра

virtual void Aircraft::getImage(GenericImage&)=0; 
void Drone::getImage(Image&); 

где Image является подкласс GenericImage Drone является подклассом Aircraft.

Как я могу требовать класс Drone иметь getImage(any subclass of genericImage&) метод без компилятора жалуясь, что genericImage и Image не то же самое? Я хочу, чтобы конечный пользователь/разработчик мог определить свой собственный класс дронов со своим собственным форматом изображения, который расширяет genericImage, но независимо от того, что они создают, они ДОЛЖНЫ предоставить функциональность, чтобы получить изображение из своего беспилотного летательного аппарата.

ответ

1

Не принимайте параметр out, просто возвращайте изображение. Возвращаемым типам разрешено быть covariant. Это означает, что до тех пор, как Image фактически публично происходит от GenericImage, это будет хорошо:

virtual GenericImage& Aircraft::getImage() = 0; 
virtual Image& Drone::getImage(); 
+0

Спасибо. Это именно то, что я искал. – imjojo42

+0

@user: Вопрос в том, почему вы действительно хотите использовать производное изображение в производном самолете? Почему бы просто не вернуть «GenericImage» там тоже? – Xeo

+0

Причина этого в том, что каждый самолет имеет другой формат изображения, который он возвращает. Поэтому каждый самолет будет иметь другой формат, характерный для этого самолета, но все самолеты будут иметь изображение. – imjojo42

0

Это не представляется возможным изменить параметры таким образом, это не должно быть, потому что, как правило, нарушают Лисков принцип замещения (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(); } 
};