дочерний объект как параметр - PullRequest
0 голосов
/ 11 января 2012

Я хочу сделать что-то вроде следующего:

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

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

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

Ответы [ 2 ]

1 голос
/ 11 января 2012

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

virtual GenericImage& Aircraft::getImage() = 0;
virtual Image& Drone::getImage();
0 голосов
/ 11 января 2012

Невозможно изменить параметры таким образом, и не должно быть, потому что это, как правило, нарушает принцип подстановки Лискова (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(); }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...