Constructor Behavior

Discussion in 'C++' started by Randy, Sep 12, 2007.

  1. Randy

    Randy Guest

    Hi.

    I am learning Design Patterns so I pulled this piece of code off the
    ng (decorator) . Now I am going through it with the debugger and
    seeing what does what and I have found something I just don't
    understand.

    The constructor for CCoffeeDecorator has this in the list
    CCoffeeComponent().

    >> CCoffeeDecorator( CCoffeeComponent* pComponent = 0) : CCoffeeComponent(), m_pComponent( pComponent ) {};


    I see it hitting the CCoffeeComponent() constructor ... but I can't
    figure out what this accomplishes. The only thing I can think of, is
    that this sets the pointer type to CCoffeeComponent ... but I don't
    understand the mechanics are behind it.

    Randy



    #include <iostream>
    #include <string>

    using namespace std;

    /*
    *******************************************************************************************************
    abstract base class ** normal - any class can be decorated.
    hide constructor prevent construction of a plain component
    *
    ********************************************************************************************************/
    class CCoffeeComponent {
    public:
    virtual string Info() = 0;

    protected:
    CCoffeeComponent () {};
    string m_Info;
    };

    /*
    *******************************************************************************************************
    Furthermore we need a decorator class that "is-a" component and
    stores a
    pointer to a passed component object:
    NOTE: the default NULL-pointer that is used as an end-marker of
    the component chain
    *
    ********************************************************************************************************/
    class CCoffeeDecorator : public CCoffeeComponent {
    public:
    CCoffeeDecorator( CCoffeeComponent* pComponent = 0) :
    CCoffeeComponent(), m_pComponent( pComponent ) {};

    public:
    virtual string Info() {
    if( !m_pComponent )
    return string("");

    return m_pComponent->Info();
    }; // delegate info call to actual
    implementation

    protected:
    CCoffeeComponent* m_pComponent;

    };

    //This base implementation of the decorator delegates any Info() calls
    to its
    //wrapped component if there is any. In principle we've got the tools
    to
    //create different component combinations at our fingertips. Now we
    get down
    //the some sample component implementations:

    // create different decorator implementations
    class CEspresso: public CCoffeeDecorator
    {
    public:
    CEspresso( CCoffeeComponent* pComponent = 0) :
    CCoffeeDecorator(pComponent ) {};
    // extend info implementation and delegate to base class
    string Info() { return CCoffeeDecorator::Info() + string("
    espresso"); };
    };

    // create different decorator implementations
    class CSteamedMilk: public CCoffeeDecorator
    {
    public:
    CSteamedMilk( CCoffeeComponent* pComponent = 0) :
    CCoffeeDecorator(pComponent ) {};
    // extend info implementation and delegate to base class
    string Info() { return CCoffeeDecorator::Info() + string(" steamed
    milk"); };
    };

    // create different decorator implementations
    class CFoamedMilk: public CCoffeeDecorator
    {
    public:
    CFoamedMilk( CCoffeeComponent* pComponent = 0) :
    CCoffeeDecorator(pComponent ) {};
    // extend info implementation and delegate to base class
    string Info() { return CCoffeeDecorator::Info() + string(" foamed
    milk"); };
    };

    class CSugar: public CCoffeeDecorator
    {
    public:
    CSugar( CCoffeeComponent* pComponent = 0) :
    CCoffeeDecorator( pComponent ){};
    // extend info implementation and delegate to base class
    string Info() { return CCoffeeDecorator::Info() + string("
    sugar"); };
    };

    class CMug: public CCoffeeDecorator
    {
    public:
    CMug( CCoffeeComponent* pComponent = 0) :
    CCoffeeDecorator( pComponent ){};
    // extend info implementation and delegate to base class
    string Info() {
    return CCoffeeDecorator::Info() + string(" mug");
    };
    };

    int main()
    {
    /*
    The pointer type is component, however the object type is
    Decorator. This is the
    jist of virtual/polymorphism.

    The recursion here is because the constructor for the decorator is
    */
    CCoffeeComponent* pCappucino= new CEspresso( new CSugar( new
    CFoamedMilk( new CMug) ) );
    CCoffeeComponent* pMocca = new CEspresso( new CSugar( new CMug ) );
    CCoffeeComponent* pEmpty = new CMug;

    cout << "Cappucino components: ";
    cout << pCappucino->Info() << endl;
    cout << "Mocca components: ";
    cout << pMocca->Info() << endl;
    cout << "Empty components: ";
    cout << pEmpty->Info() << endl;

    delete pCappucino;
    delete pMocca;

    system("PAUSE");
    return EXIT_SUCCESS;

    return 0;

    }
    Randy, Sep 12, 2007
    #1
    1. Advertising

  2. Randy

    Randy Guest

    I don't know how I managed to butcher the English language so bad ...
    Here is what I am actually asking ...

    In the CCoffeeDecorator constructor list, there is a call to the
    parent class constructor, CCoffeeComponent(). I can't figure out what
    this accomplishes, in context of this Decorator example.
    Randy, Sep 12, 2007
    #2
    1. Advertising

  3. Randy wrote:
    > I am learning Design Patterns so I pulled this piece of code off the
    > ng (decorator) . Now I am going through it with the debugger and
    > seeing what does what and I have found something I just don't
    > understand.
    >
    > The constructor for CCoffeeDecorator has this in the list
    > CCoffeeComponent().
    >
    >>> CCoffeeDecorator( CCoffeeComponent* pComponent = 0) :
    >>> CCoffeeComponent(), m_pComponent( pComponent ) {};

    >
    > I see it hitting the CCoffeeComponent() constructor ... but I can't
    > figure out what this accomplishes. The only thing I can think of, is
    > that this sets the pointer type to CCoffeeComponent ... but I don't
    > understand the mechanics are behind it.


    Not sure what your confusion is. CCoffeeDecorator inherits from
    CCoffeeComponent. The first item in the constructor initialiser list
    is the base class initialiser. It does not have to be there since
    CCoffeeComponent is a class that can be default-initialised without
    being explicitly mentioned in the initialiser list.

    In reality it accomplishes nothing. You can omit it and the base
    class subobject will still be constructed.

    >
    > Randy
    >
    >
    >
    > #include <iostream>
    > #include <string>
    >
    > using namespace std;
    >
    > /*
    > *******************************************************************************************************
    > abstract base class ** normal - any class can be decorated.
    > hide constructor prevent construction of a plain component
    > *
    > ********************************************************************************************************/
    > class CCoffeeComponent {
    > public:
    > virtual string Info() = 0;
    >
    > protected:
    > CCoffeeComponent () {};
    > string m_Info;
    > };
    >
    > /*
    > *******************************************************************************************************
    > Furthermore we need a decorator class that "is-a" component and
    > stores a
    > pointer to a passed component object:
    > NOTE: the default NULL-pointer that is used as an end-marker of
    > the component chain
    > *
    > ********************************************************************************************************/
    > class CCoffeeDecorator : public CCoffeeComponent {
    > public:
    > CCoffeeDecorator( CCoffeeComponent* pComponent = 0) :
    > CCoffeeComponent(), m_pComponent( pComponent ) {};
    >
    > public:
    > virtual string Info() {
    > if( !m_pComponent )
    > return string("");
    >
    > return m_pComponent->Info();
    > }; // delegate info call to actual
    > implementation
    >
    > protected:
    > CCoffeeComponent* m_pComponent;
    >
    > };
    > [..]


    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Sep 12, 2007
    #3
  4. Randy

    Randy Guest

    Thank you Victor

    That was exactly my confusion. As I am new, I just assume that I am
    missing a finer point.

    Randy
    Randy, Sep 12, 2007
    #4
  5. Randy wrote:
    > That was exactly my confusion. As I am new, I just assume that I am
    > missing a finer point.


    The finer point here *may* be that "everything should be initialised
    or something bad's gonna happen" rule is a good rule to live by. But
    of course the author would know better, and if they didn't explain
    (there or elsewhere in the book), you and I are left to guess...

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Sep 12, 2007
    #5
  6. Randy

    James Kanze Guest

    On Sep 12, 4:34 am, "Victor Bazarov" <> wrote:
    > Randy wrote:
    > > That was exactly my confusion. As I am new, I just assume that I am
    > > missing a finer point.


    > The finer point here *may* be that "everything should be initialised
    > or something bad's gonna happen" rule is a good rule to live by. But
    > of course the author would know better, and if they didn't explain
    > (there or elsewhere in the book), you and I are left to guess...


    Let's not forget that the author is providing this code as an
    example. In practice, the base class might not have a default
    constructor (or the default constructor might not be the one we
    want), so his example includes a call to the base class
    constructor. (But I'm not too sure about this. In the
    decorator pattern, the base class will almost surely be an
    interface, whose only constructors are the compiler generated
    default and copy constructors.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Sep 12, 2007
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Giulio
    Replies:
    9
    Views:
    1,030
    Patrick Kowalzick
    Jun 25, 2003
  2. Brett Irving
    Replies:
    3
    Views:
    3,321
    John Harrison
    Jun 29, 2003
  3. lallous
    Replies:
    5
    Views:
    8,806
    David Harmon
    Jan 23, 2004
  4. Aire
    Replies:
    3
    Views:
    457
    Mike Wahler
    Jan 25, 2004
  5. Generic Usenet Account
    Replies:
    10
    Views:
    2,204
Loading...

Share This Page