Compile-time polymorphism
In Chapter 5, we discussed dynamic, or runtime, polymorphism. We used it to define an interface for uart, which was implemented by the uart_stm32 class. The gsm_lib class has a dependency on the uart interface only, not on the concrete implementation, which is contained in uart_stm32. This is called loose coupling and allows us to have portable code for the gsm_lib class.
We can easily supply gsm_lib with another uart interface implementation on a different hardware platform. This principle is called dependency inversion. It says that high-level modules (classes) shouldn’t depend on low-level modules and that both should depend on abstractions (interfaces). We can implement this principle by using inheritance and virtual functions in C++.
Virtual functions result in indirection, causing the runtime overhead and increased binary size needed for their implementation. They allow runtime dispatching of function calls, but they come with a price...