2

I'd like to use the Decorator Pattern in C++ and still be able to rely on the signature/identity of the decorated object. Is it possible to do it in C++?

That is, I'd like to decorate a component:

class Component {
  public:
      Component();
      virtual void doSomething();
}

with a decorator:

class Decorator : public Component {
  public:
      Decorator(Component*);
      virtual void doSomething();
  private:    
      Component* _component;
}

such that when I do:

Component foo;
Decorator(&foo) bar;
std::cout << typeid(bar).name() << std::endl;

it prints "Component" instead of "Decorator".

(This is actually pretty simple to do in Python using the decorator module but I'm learning C++ at the moment and don't even know where to start looking for an answer to this question.)

This is useful in case I want to extend the Component class but still be able to use it in a transparent way (as if it wouldn't have been extended):

class ExtendDecorator : public Decorator {
  public:
      ExtendDecorator(Component*);
      virtual void doSomething();    

  private:
      void doSomethingMore();
}

void ExtendDecorator::doSomething() {
    Decorator::doSomething();
    doSomethingMore();
}
gnzlbg
  • 7,135
  • 5
  • 53
  • 106
  • Can you expand on what you mean by this? (i.e. what problems are you anticipating?) – Oliver Charlesworth Jun 24 '12 at 18:08
  • Possible duplicate: http://stackoverflow.com/questions/2988066/decorator-pattern-in-c – Andrew Tomazos Jun 24 '12 at 18:09
  • http://stackoverflow.com/questions/5205491/whats-this-stl-vs-c-standard-library-fight-all-about/5205571#5205571 – Griwes Jun 24 '12 at 18:26
  • Could you elaborate on how to preserve the signature of the object because I wasn't able to understand that from your answers. Thanks! – gnzlbg Jun 24 '12 at 18:30
  • I think you need to understand the way virtual functions work in C++. I have a feeling here that you are assuming that Python and C++ work similarly. In the example above, you are really extending the *same* virtual functions - by extending, I mean that the virtual function in the derived classes will override the base class implementations. The way you are trying to call Decorator's doSomething is the syntax for calling static functions in C++. Not what you are trying to achieve. – Specksynder Jun 24 '12 at 18:37
  • 2
    @Specksynder - no, he's just being explicit about calling the base class's method. Take a look at http://stackoverflow.com/questions/357307/c-how-to-call-a-parent-class-function-from-derived-class-function – derekerdmann Jun 24 '12 at 18:42

1 Answers1

4

Since in C++ overloading operator typeid is not allowed - the only solution which I can propose is to add virtual method returning type_info for decorated type:

class Component {
  public:
      Component();
      virtual void doSomething();
      virtual const std::type_info& decorated_type() const 
      { return typeid(*this); } 
};

class Decorator : public Component {
  public:
      Decorator(Component*);
      virtual void doSomething();
      virtual const std::type_info& decorated_type() const 
      { return typeid(*_component); } 
  private:    
      Component* _component;
};

Maybe better version for Decorator::decorated_type() const:

virtual const std::type_info& decorated_type() const 
{ return _component->decorated_type(); } 
PiotrNycz
  • 23,099
  • 7
  • 66
  • 112
  • 1
    @GonzaloBG - see my update for `Decorator::decorated_type() const`. Maybe it will better suit for you... – PiotrNycz Jun 25 '12 at 07:59