They can improve reuse by letting old code call new code provided at run time (virtual functions) or compile time (templates).
Before OO and generic programming came along, reuse was accomplished by having new code call old code. For example, a programmer might write some code that called some reusable code such as
With OO and generic programming, reuse can also be accomplished by having old code call new code. For example, a programmer might write some code that is called by a framework that was written by their great, great grandfather. There’s no need to change great-great-grandpa’s code. In fact, for dynamic binding with virtual functions, it doesn’t even need to be recompiled. Even if all you have left is the object file and the source code that great-great-grandpa wrote was lost 25 years ago, that ancient object file will call the new extension without anything falling apart.
That is extensibility, and that is OO and generic programming for powerful reusable abstraction.