Uniqueness of C++ methods and class member variables
I have made a number of recent postings focused on C++ issues, responding to a number of questions. I have a few more planned, but I was intending to give this topic a rest for a while. However, my eye was caught by one question, which I felt had some potential:
I learned that Objective C objects are not complete copies of the class object. In other words, only the data and certain static structures are independent for each instance of a class. The methods are kept in a central location for all objects to use. Is there any C++ implementation for embedded systems that use this feature?
This sounds simple, but this question raises quite a few issues …
First off, Objective C is of limited interest to embedded developers. So a comparison with C++ may be of limited value.
In C++, there is no such thing as a “class object” really. A class [or a struct] is a “recipe” to make objects. Defining a class/struct does not create any code or data. Instantiating the class – i.e. defining objects [or variables, if you prefer] – is when real code and data is created/allocated. It is at that point that some discussion about memory usage makes sense. Here is a simple class definition:
class example { public: int local_variable; static int shared_variable; void out_of_line_function(int p); int inline_function(int x) { local_variable = x; return x; }; };
void example::out_of_line_function(int p) { shared_variable = p; }
example class_instantiation_1, class_instantiation_1;
Here we have a class – example – and an object instantiated from it – class_instantiation_1 and class_instantiation_2.
Now we can look at each member variable and function [method] individually:
- The first member variable is local_variable. This is allocated space when an object is created and each object has its own copy of this variable. So, class_instantiation_1.local_variable refers to one memory location and class_instantiation_2.local_variable to another. This is, I believe , exactly what might be expected.
- The next member variable is shared_variable. As this is declared static the storage allocated to this variable is shared between every instance of the class. So, class_instantiation_1.shared_variable and class_instantiation_2.shared_variable refer to the same data.
- The first method in the class is out_of_line_function(). Normally, a single copy of this code will exist and be shared by all instances of the class. A separate copy of the code for each class instantiation would be a ridiculous waste of resources – the kind of thing that makes embedded developers lose sleep. However, there is the possibility that the compiler, if the optimization options allow, might decide to inline this function – i.e. place a copy of the code at each call site, instead of incurring the call/return runtime overhead. This possibility cannot be determined from the code alone, but the inlining is only possible if this definition is in a header file [as the class definition would be], instead being in another .cpp file.
- The code for the second method – inline_function() – is defined within the class body, which is a shorthand way to tell the compiler that an inline optimization may be appropriate; it is equivalent to using the inline keyword. However, this is only a suggestion and, once again, the exploitation of this possibility cannot be determined from the code alone.
Broadly speaking, the member variables of an object may be local or shared; this is determined by the programmer. Methods may be out of line [shared] or inline [sort of local], but this is determined largely by the compiler.
Once again, I acknowledge the input from my colleague Jon Roelofs on this blog posting.