Monday, 24 August 2020

C++ Interfaces Explained

When designing a program, using interfaces improves the program by drastically lowering coupling.

This first diagram, we can see that the EntityManager depends on the Renderer class. This is bad because programs should "depend upon abstractions not concretions", if the Renderer class changes then EntityManager will break too.

Therefore we should 'fix' the Renderers interface so that other class that use the Renderer, will not have to be changed when the renderer functions change. To do this we use what is called an "Interface" class (interface in Java and C# are natively supported but not in C++). The "Interface" class is in fact a PIMPL (pointer to implementation) used to create the boundary between implementation and abstraction.

An "Interface" class in C++ is a polymorphic base class with no implementation (code,data.etc) just function signatures. The reason why it holds nothing but function signatures. One reason why an interface has no implementation is because (see example double-dispatch below) the "Interface" classes can be forward declared and linked at link time, this means the "Interface" class can't contain any implementation, only function signatures, otherwise we receive "Duplicate Symbols" error from the linker when we try to use them.

Without interface
Without the IRenderer interface

This second diagram shows the Renderer concrete class, they are exactly the same other than Renderer is replaced with the abstract polymorphic class "IRenderer" to seperate the Renderer heirachy from the EntityManager.

With the IRenderer interface

IRenderer interface /PIMPL

Although it might seem redundant to duplicate the Renderer interface as IRenderer, it is infact a cornerstone of "Designing by contract", using interfaces you can define contracts between class heirachies.

OOP - Recovering lost class types

 Normally casting is used to convert classes to other classes, however this operation can break the type system. For example, a "List&q...