I was studing the Composit Pattern and experienced an unexpected behaviour of the following code:
namespace Composit
{
class Component
{
public:
virtual ~Component() { }
virtual void operation() = 0;
protected:
private:
};
class Leaf : public Component
{
public:
Leaf() { }
virtual ~Leaf() { }
void operation() override
{
// Implementation of operation for a leaf
std::cout << this << ": I am a leaf" << std::endl;
}
protected:
private:
};
class Composit : public Component
{
public:
Composit(Component& x) :
child_(x)
{ }
virtual ~Composit() { }
void operation() override
{
// Implementation of operation for a composit
std::cout << this << ": I am a composit! " << std::endl;
child_.operation();
}
protected:
Component& child_;
private:
};
}
int main()
{
Composit::Leaf a;
Composit::Composit b(a); // b->a
Composit::Composit c(b); // c->b->a
Composit::Composit d(c); // d->c->b->a
}
I expected, as shown in the comments, to have some form of a recursive link. Instead I discovered that "child_" for "b", "c" and "d" reference "a". I can get the expected behaviour when the parameter to the Composit constructor is a pointer to a Component.
Composit(Component* x) :
child_(*x)
{ }
and the definitions of the variables b, c, d obviously use the addresses of a, b, c
Composit::Leaf a;
Composit::Composit b(&a); // b->a
Composit::Composit c(&b); // c->b->a
Composit::Composit d(&c); // d->c->b->a
Is there a reason for the version using the reference as a parameter not to work as I expected?
Thanks.
Edit: I tried this code
void f(Composit::Component& x)
{
x.operation();
}
int main()
{
Composit::Leaf a;
Composit::Composit b(a); // b->a
Composit::Composit c(b); // c->b->a
Composit::Composit d(c); // d->c->b->a
f(d);
f(c);
f(b);
f(a);
}
and got this output
00D7F858: I am a composit!
00D7F888: I am a leaf
00D7F868: I am a composit!
00D7F888: I am a leaf
00D7F878: I am a composit!
00D7F888: I am a leaf
00D7F888: I am a leaf
This is instead what I get when I pass the pointers
int main()
{
Composit::Leaf a;
Composit::Composit b(&a); // b->a
Composit::Composit c(&b); // c->b->a
Composit::Composit d(&c); // d->c->b->a
f(d);
f(c);
f(b);
f(a);
}
00DEF9D4: I am a composit!
00DEF9E4: I am a composit!
00DEF9F4: I am a composit!
00DEFA04: I am a leaf
00DEF9E4: I am a composit!
00DEF9F4: I am a composit!
00DEFA04: I am a leaf
00DEF9F4: I am a composit!
00DEFA04: I am a leaf
00DEFA04: I am a leaf