I'm trying to implement something following the decorator pattern, but I cannot seem to obtain from a shared_ptr the same run-time behaviour I can get through normal pointers. I have a basic class I (interface) with a virtual method, then I derive from it two classes:
Then I want to be able to build a B object with its pointer pointing to an A, so that when I call the common methods I call the A ones not the I ones.
I can do this if I make the pointer in B in the usual way (in the code example, see the class B_basic and the object bb in the main).
But if I make this pointer like a shared_ptr to I it calls the method from I even if I build it pointing to an actual A (in code see the B_shared class and the object bs)
class I {
public:
virtual void method() {cout<<"I\n";}
virtual ~I() = default;
};
class A : public I {
public:
virtual void method() {cout<<"A\n";}
};
class B_shared : public I {
public:
shared_ptr<I> shared_pointer;
B_shared(const I& i) : shared_pointer(make_shared<I>(i)) {}
virtual void method() {
cout<<"B_shared > ";
shared_pointer->method();
}
};
class B_basic : public I {
public:
I* basic_pointer;
B_basic(I* i) : basic_pointer(i) {}
virtual void method() {
cout<<"B_basic > ";
basic_pointer->method();
}
};
int main() {
A a;
B_shared bs(a);
B_basic bb(&a);
bs.method(); // B_shared > I
bb.method(); // B_basic > A
}
What am I doing wrong?
This is object slicing.
In the following line you make a copy of the instance i
of type A
to type I
. Thus the original type A
is sliced to base type I
.
shared_pointer(make_shared<I>(i))
In raw pointer version basic_pointer(i)
, you save the pointer itself, no slicing.