Everything that inherits from Object can be stored in objects. Using std::shared_ptr means that the objects are destroyed as soon as they are not longer needed.
The container cannot store different types. Therefore, we do not put those objects into the container. We store pointers in the container. We can reach the actual objects via those pointers.
Public inheritance represents IS-A relationship. Rectangle is an Object. In ideal case the interface of Object is sufficient and we can use all Objects as Objects no matter what their actual shape is. There is dynamic_cast for accessing the interface of a derived type.
Note that:
1 2 3 4 5 6 7 8
container_type<Object> foo;
Circle bar;
foo.insert ( bar );
// effectively perfoms:
Object gaz;
Circle bar;
gaz = bar;
The gaz is an Object. The gaz is not a Circle. The assignment copies only the base class bits from Circle object into Object object. Loss of data. Slicing.
However:
1 2 3
Rectangle * pr = ...;
Object * po;
po = pr;
An address is an address. The po points to the same Rectangle object as the pr does.
When you have a list of pointers to Objects, the actual pointed to objects can be various derived types. Polymorphism.
Don't see a strong reason to mess around with pointers and dynamically allocated objects (in particular, objects with shared ownership semantics) in user code.