Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
234 views
in Technique[技术] by (71.8m points)

oop - Issues implementing double dispatch in C++

Thanks for taking the time to look at my question. I am trying to implement double dispatch in C++ but It doesn't seem to be taking. I suppose there may be something that I am missing? I don't believe object slicing is the issue as I am using pointers. I have read about issues with overload resolution and that double dispatch was a way around that. Any help is appreciated.

Here is my code

class ReactType;
class ConditionerBase
  {
  public:
    ConditionerBase(/* args */){};
    ~ConditionerBase(){};
    virtual void visit(ReactType* reactor);
  };

  class ReactType
  {
  public:
    ReactType(/* args */){};
    ~ReactType(){};
    virtual void accept(ConditionerBase *conditioner);
  };
  
  class IdealReactType: public ReactType
  {
  public:
    IdealReactType(/* args */){};
    ~IdealReactType(){};
    virtual void accept(ConditionerBase *conditioner);
  };

  class Conditioner : public ConditionerBase
  {
  public:
    Conditioner(/* args */){};
    ~Conditioner(){};
    virtual void visit(ReactType* reactor){std::cout<<"Visited unknown reactor"<<std::endl;};
    virtual void visit(IdealReactType* ideal_reactor){std::cout<<"Visited ideal_reactor"<<std::endl;};
  };

  void ReactType::accept(ConditionerBase *conditioner){conditioner->visit(this);};
  void IdealReactType::accept(ConditionerBase *conditioner){conditioner->visit(this);};
  void ConditionerBase::visit(ReactType* reactor){std::cout<<"Base"<<std::endl;};

void doubleDispatchExample()
{

  std::vector<ReactType*> reactors;
  ReactType* unknown = new ReactType();
  IdealReactType* ideal_reactor = new IdealReactType();
  reactors.push_back(unknown);
  reactors.push_back(ideal_reactor);
  Conditioner conditioner;
  for (size_t i = 0; i < 2; i++)
  {
    reactors.at(i)->accept(&conditioner);
  }
  delete unknown;
  delete ideal_reactor;
}

I want the output to be

Visited unknown reactor
Visited ideal reactor

but instead I get

Base
Base

when calling doubleDispatchExample()

It was suggested that I make the functions virtual which gives me

Visited unknown reactor
Visited unknown reactor
question from:https://stackoverflow.com/questions/65853149/issues-implementing-double-dispatch-in-c

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I found out that the ConditionerBase needs both classes of the overloaded functions and it gives me the desired output. Changing it to the following gives the output I want.

class ReactType;
class IdealReactType;
class ConditionerBase
  {
  public:
    ConditionerBase(/* args */){};
    ~ConditionerBase(){};
    virtual void visit(ReactType* reactor);
    virtual void visit(IdealReactType* reactor);
  };

  class ReactType
  {
  public:
    ReactType(/* args */){};
    ~ReactType(){};
    virtual void accept(ConditionerBase *conditioner);
  };
  
  class IdealReactType: public ReactType
  {
  public:
    IdealReactType(/* args */){};
    ~IdealReactType(){};
    virtual void accept(ConditionerBase *conditioner);
  };

  class Conditioner : public ConditionerBase
  {
  public:
    Conditioner(/* args */){};
    ~Conditioner(){};
    virtual void visit(ReactType* reactor){std::cout<<"Visited unknown reactor"<<std::endl;};
    virtual void visit(IdealReactType* ideal_reactor){std::cout<<"Visited ideal_reactor"<<std::endl;};
  };

  void ReactType::accept(ConditionerBase *conditioner){conditioner->visit(this);};
  void IdealReactType::accept(ConditionerBase *conditioner){conditioner->visit(this);};
  void ConditionerBase::visit(ReactType* reactor){std::cout<<"Base Reactor"<<std::endl;};
  void ConditionerBase::visit(IdealReactType* reactor){std::cout<<"Base Ideal"<<std::endl;};

void doubleDispatchExample()
{

  std::vector<ReactType*> reactors;
  ReactType* unknown = new ReactType();
  IdealReactType* ideal_reactor = new IdealReactType();
  reactors.push_back(unknown);
  reactors.push_back(ideal_reactor);
  Conditioner conditioner;
  for (size_t i = 0; i < 2; i++)
  {
    reactors.at(i)->accept(&conditioner);
  }
  delete unknown;
  delete ideal_reactor;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...