Constructor Behavior

R

Randy

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().

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;

}
 
R

Randy

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.
 
V

Victor Bazarov

Randy said:
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().


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
 
R

Randy

Thank you Victor

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

Randy
 
V

Victor Bazarov

Randy said:
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
 
J

James Kanze

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.)
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,528
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top