This is a follow-up to my Minimal C++ article. It might be helpful to read that article first, in order to understand the context better.
Here, I present a relatively refined—and featherweight—method for using C++ in “micro” environments: think 16- or 32-bit microcontrollers with memory on the order of 64–256 KiB of storage, usually split between the program and runtime memory (RAM).
This is the (extremely) minimal C++ runtime, which I’ll refer to later.
|
|
Keep in mind that this runtime support code is intended to support only the bare minimum required to compile (useful) C++ code. It does NOT provide any support for exceptions or RTTI. If you need those features in your program, the Minimal C++ method won’t work for it; use the full C++ language and a suitable runtime instead.
Given:
-fno-rtti -fno-exceptions
), and— it is possible to write C++ that is very lean. It essentially results in the C++ language being used as syntactic sugar on top of C.
As written, it does require that the C functions calloc(3)
,
free(3)
, and abort(3)
are present. However, the
calls to these functions can be replaced by any code that has the same
semantic meaning. If the program has a custom heap implementation which
ensures that only 4 KiB of the system’s memory available that way, then
it makes sense to call the custom allocator’s functions, and not the
ones which are provided by the standard C library.
There are several different reasons why one might want to do this:
extern "C"
wrapper for the API of the C++ class.And of course, there are plenty of other reasons that I haven’t listed here. Regardless of the reason, it is truly this easy to get C++ into a previously C-only code base—and it can be useful, too.
Well, actually, that’s not quite true. Though it is true that most C++ programmers write code that tends to be heavy for one reason or another.
C++—the language, excluding the runtime—is not much heavier than C. In fact, for a lot of code, C++ will generate exactly the same code as C, and in same cases (because it is more knowledgeable about things like context) it can both generate code that is more efficient than the C compiler can, and enable the programmer to make more efficient use of time by reducing repetition.
In C++, a class can have methods which are virtual
, meaning that they
can be overridden by a subclass, and given a pointer or reference to the
base class, the virtual function in the most derived type will be called.
Methods can also be “pure virtual” methods, meaning that they are part of
the interface, but have no implementation in the base class, making
the base class abstract. Pure virtual methods must be implemented
or an instance of the class cannot be created.
Virtual methods require that the implementation method be found through
indirection at runtime, using an apparatus known as the vtable
for the
object. While this does carry with it a performance impact, it is
negligible for nearly all types of code, and compilers will optimize that
impact away at every available chance. In other words: it’s no worse
than a struct carrying function pointers—and actually it’s better,
because:
One of the most often criticized features of C++ is templates. In C++, it is possible to write a function or a class which is parameterized by a type, and then when it is used with a concrete type, the template is used to instantiate C++ code that works with the concrete type.
That’s probably about as clear as a glass of milk, so I’ll try explaining how it works by example.
This is a template:
|
|
To actually use this template, code like this is present somewhere:
|
|
Which instantiates the template in the compilation unit in which it is
mentioned. If array_t
were a regular class here, it would have functions
named things like array_t::operator[]
. However, it will actually wind up
having functions which are named like array_t<uint8_t>::operator[]
, because
it is a template type, and uint8_t
is the type it is instantiated for.
The takeaway here? You can have type-safe, memory-managed containers with minimal code, simply by using C++ anywhere you’d use plain C!
I hope that this helps to clarify a bit about the how to use it over the previous Minimal C++ article. I’d like to show some production-quality, non-trivial examples here at some point, hopefully soon.
Thanks for reading.
If you appreciated this article (or anything else I’ve written), please consider donating to help me out with my expenses—and thanks!