Imagine: you have a nice heirarchy of objects, simple and complete. Call them GamePieces. You then invent a second object which needs to do distinct things to each of them. Maybe it's named BoardGame2.

The object oriented way to deal with this problem is to give the object heirarchy a virtual function for all the objects to implement. Unfortunately, this pollutes the simplicity of the GamePieces with knowledge of BoardGame2. You already went down this road before with BoardGame1 and you will do it again with BoardGame3.

Each time you reuse the GamePieces to invent a new BoardGame, the pieces will become smarter and smarter. It will not be possible to compile only BoardGame1. It requires the GamePieces which know about BoardGame2, 3, and so on, and it will trigger the compilation of all of them.

One solution would be to extend each of the GamePieces with logic for BoardGameN. Of course, that means you'll have (M+1)*N different GamePieces objects. If the extension added data members, it might be justified, but if all you are adding is methods (algorithms), it's a bit heavy-handed.

Eventually, you are forced to choose between

Blech.

Another (perhaps more familiar) example is persisting objects in a database in a client-server application.

The server only needs the data members and the algorithms to save the object to the database.

The client only needs the data members and the front-end logic (all the reasons you made them objects in the first place).

Including database logic in the objects pollutes the client side with references to database packages.