Полиморфизм с указателями / boost :: shared_ptr - PullRequest
0 голосов
/ 26 октября 2011

Рассмотрим следующий пример полиморфизма в C ++.Для меня это неожиданное поведение, которое, вероятно, заключается в том, что я все еще слишком много думаю о Java.Вопрос для меня сейчас: как мне получить пример указателя для вызова более конкретного метода.

#include <iostream>
#include <string.h>
#include <boost/tr1/memory.hpp>

class Image {
 public:
  Image(std::string className = "Image") 
      : className_(className)
    {}

  virtual ~Image() {}

  virtual std::string className() {
    return className_;
  }

 private:
  std::string className_;
};

class RightImage : public Image {
 public:
  RightImage()
      : Image("RightImage")
    {}
};

class Processor{
 public:
  void process(Image& image){
    std::cout << "Invoking process(Image& image) with image of type \"" << image.className() << "\"" << std::endl;
  }
  void process(RightImage& rightImage){
    std::cout << "Invoking process(RightImage& rightImage) with rightImage of type \"" << rightImage.className()  << "\"" << std::endl;
  }

  void process(Image* image){
    std::cout << "Invoking process(Image* image) with image of type \"" << image->className() << "\"" << std::endl;
  }
  void process(RightImage* rightImage){
    std::cout << "Invoking process(RightImage* rightImage) with rightImage of type \"" << rightImage->className()  << "\"" << std::endl;
  }
};

int main(int argc, char **argv) {
      std::tr1::shared_ptr<Image> rightImageSharedPtr(new RightImage());
      Image* rightImagePointer = new RightImage();
      RightImage rightImage;
      Processor processor;
      std::cout << "value:                   ";
      processor.process(rightImage);
      std::cout << "shared_ptr:              ";
      processor.process(*rightImageSharedPtr);
      std::cout << "old fashioned pointer 1: ";
      processor.process(*rightImagePointer);
      std::cout << "old fashioned pointer 2: ";
      processor.process(rightImagePointer);
}

Вывод этой программы:

значение: вызов процесса(RightImage & rightImage) с rightImage типа «RightImage»

shared_ptr: процесс вызова (изображение и изображение) с изображением типа «RightImage»

устаревший указатель 1: процесс вызова (изображение и изображение) сизображение типа "RightImage"

старомодный указатель 2: процесс вызова (Image * image) с изображением типа "RightImage"

Как сделать так, чтобы последние три примера также вызывалиprocess(RightImage&) и process(RightImage*)?

Ответы [ 3 ]

1 голос
/ 26 октября 2011

Я думаю, что вы хотите что-то вроде двойной отправки / Шаблон посетителя, чтобы решить вашу проблему.

Информация о том, какой тип вашего изображения действительно находится под интерфейсом, доступна только внутри объекта. Поэтому вам нужно вызвать виртуальный метод для объекта изображения, чтобы получить базовый тип.

Пример:

class Image{
    virtual void process(Processor &processor)=0;
}

class RightImage{
    virtual void process(Processor &processor){
        processor.process(this);
    }
}

Конечно, вы также можете выполнять обработку внутри класса изображений в методе process () - Method, но я подозреваю, что вы хотите, чтобы разные типы процессоров работали с разными типами изображений. Другой вариант, который, возможно, немного чище, заключается в том, чтобы процессор вызывал виртуальные методы для отдельных этапов обработки, где они различаются для типов изображений.

1 голос
/ 26 октября 2011

Рядом с двойной диспетчеризацией , предложенной tokage, вы также можете иметь только 1 функцию Process () с ссылкой на базовый класс в качестве параметра и затем использовать полиморфизм, вызывая виртуальную функцию базового класса внутри Функция Process ().

0 голосов
/ 26 октября 2011

Перегрузка разрешена для статических типов аргументов функции, поэтому вам нужно объявить ваши переменные как

  std::tr1::shared_ptr<RightImage> rightImageSharedPtr(new RightImage());
  RightImage* rightImagePointer = new RightImage();

Альтернативой является выполнение dynamic_cast перед вызовом каждой функции, что является просто более сложным способом сделать то же самое.

...