简体   繁体   English

使用指针/ boost :: shared_ptr的多态性

[英]Polymorphism with pointers/boost::shared_ptr

Consider the following example of polymorphism in C++. 考虑以下C ++中的多态性示例。 To me, this is unexpected behavior, which probably lies in the fact that I am still thinking too much in Java. 对我来说,这是意想不到的行为,这可能在于我在Java中仍然在思考太多。 The question to me is now: How do I get the pointer example to call the more specific method. 我现在的问题是:如何获取指针示例来调用更具体的方法。

#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);
}

The output of that program is: 该计划的输出是:

value: Invoking process(RightImage& rightImage) with rightImage of type "RightImage" value:使用类型为“RightImage”的rightImage调用进程(RightImage和rightImage)

shared_ptr: Invoking process(Image& image) with image of type "RightImage" shared_ptr:使用“RightImage”类型的图像调用进程(图像和图像)

old fashioned pointer 1: Invoking process(Image& image) with image of type "RightImage" 老式指针1:使用“RightImage”类型的图像调用进程(图像和图像)

old fashioned pointer 2: Invoking process(Image* image) with image of type "RightImage" 老式指针2:使用“RightImage”类型的图像调用进程(图像*图像)

How can I make the last three examples also call process(RightImage&) and process(RightImage*) ? 如何使最后三个示例也调用process(RightImage&)process(RightImage*)

I think you want something like double dispatch/ Visitor Pattern to solve your problem. 我想你想要像双重调度/访客模式这样的东西来解决你的问题。

The information which type your Image really is under the interface is only available inside the object. 实际上在界面下键入图像的信息仅在对象内部可用。 So you need to call a virtual method on the image object to get at your underlying type. 因此,您需要在图像对象上调用虚方法以获取基础类型。

Example: 例:

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

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

Of course you also could do the processing inside the image class in the process()-Method, but I suspect you want different kinds of processors to work on different types of images. 当然你也可以在process() - Method中对图像类进行处理,但我怀疑你想要不同类型的处理器来处理不同类型的图像。 Another option - which is a bit cleaner maybe - is to have the processor call virtual methods for the single processing steps where they differ for the image types. 另一种选择 - 可能更清洁 - 是让处理器为单个处理步骤调用虚拟方法,它们对于图像类型不同。

在tokage提出的双重调度旁边,你也可以只有一个Process()函数,基类引用作为参数,然后通过在Process()函数中调用基类的虚函数来使用多态。

Overloading is resolved on the static types of a function's arguments so you need to declare your variables as 重载是在函数参数的静态类型上解决的,因此您需要将变量声明为

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

The alternative is to perform a dynamic_cast before calling each function, which is just a more convoluted way of doing the same thing. 另一种方法是在调用每个函数之前执行dynamic_cast,这只是一种更复杂的做同样事情的方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM