Let’s make sure we understand what we did
In the original example, the abstract “body” class was used just as a handle to deal with cubes and cylinders in the same way. It did not contribute functionality at this time.
Now, however, the whole business with the color is done by the body parent class. The “children” just pass on the color information in their constructor; from that point on they are no longer involved in any color-related business. They inherit this functionality from their parent class.
There is no proliferation of the color-handling code. It’s all contained in the code for the body class.
In real life, this is the norm: Lots of aspects of the classes are dealt with at a high level in the inheritance tree, so that code does not get duplicated. Only the code which is truly class-specific (such as the getVolume and getSurface) “lives” with the actual class.
Also, for the first time, we saw a destructor. It has the name ~<classname>, ~body, ~cube, etc. We need it here to get rid of memory which we allocated. Destructors are usually found in all class definitions except in the most simple ones. More about destructors later.