Возврат указателя производного объекта из виртуального метода - PullRequest
0 голосов
/ 26 апреля 2018

Почему s1-> duplicate () не возвращает Box * в примере кода 1 ?Я бы предположил, что производный дубликат вызывается и как таковой, что Box * возвращается, но кажется, что вместо него возвращается Shape *.

Пример кода 1:

#include <iostream>

struct Shape
{
  virtual Shape* duplicate()
  {
      std::cout << "c" << std::endl;
      return new Shape;
  }
  virtual void print()
  {
    std::cout << "SHAPE" << std::endl;
  }
  virtual ~Shape() {}
};

struct Box : public Shape
{
  virtual Box* duplicate()
  {
      std::cout << "b" << std::endl;
      return new Box;
  }
  virtual void print()
  {
    std::cout << "BOX" << std::endl;
  }
};

int main(int argc, char** argv) 
{ 
  Shape* s1 = new Box;
  Box* b1 = s1->duplicate();  //ISSUE HERE
  b1->print();

  delete s1;
  delete b1;
  return 0; 
}

Ошибка: 34:27: ошибка: недопустимое преобразование из «Shape *» в «Box *» [-fpermissive]

Ответы [ 2 ]

0 голосов
/ 26 апреля 2018

C ++ является «инвариантом», а не «контравариантным», что означает, что указатель на базовый класс может содержать объект производного класса, но не наоборот.

Так в вашем коде:

Box* b1 = s1->duplicate();  //ISSUE HERE

Вы пытаетесь сохранить в b1 объект класса shape.И это неверно.

Ваша функция клонирования верна, но вы ее неправильно используете.

  • Я думаю, вы не правильно понимаете, как Polymorphism достигается и работает.

    Shape* s1 = new Box; // s1 is of Type Shape whatever the type of object it point to be.
    Box* b1 = (Box*)s1->duplicate();
    b1->print();
    
0 голосов
/ 26 апреля 2018

Вы звоните duplicate() с Shape *, поэтому возвращаемое значение равно Shape *.

Измените это:

Box* b1 = s1->duplicate();

на:

Shape *b1 = s1->duplicate();

Когда вы затем запустите свою программу, вы увидите, что b1 действительно Box.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...