C++ FAQ Celebrating Twenty-One Years of the C++ FAQ!!!
(Click here for a personal note from Marshall Cline.)
Section 9:
[9.4] How can inline functions help with the tradeoff of safety vs. speed?

In straight C, you can achieve "encapsulated structs" by putting a void* in a struct, in which case the void* points to the real data that is unknown to users of the struct. Therefore users of the struct don't know how to interpret the stuff pointed to by the void*, but the access functions cast the void* to the appropriate hidden type. This gives a form of encapsulation.

Unfortunately it forfeits type safety, and also imposes a function call to access even trivial fields of the struct (if you allowed direct access to the struct's fields, anyone and everyone would be able to get direct access since they would of necessity know how to interpret the stuff pointed to by the void*; this would make it difficult to change the underlying data structure).

Function call overhead is small, but can add up. C++ classes allow function calls to be expanded inline. This lets you have the safety of encapsulation along with the speed of direct access. Furthermore the parameter types of these inline functions are checked by the compiler, an improvement over C's #define macros.