QUIZ How do we implement run-time constants and compile-time constants inside classes?
Compile-time constants in classes The static keyword inside a class means there s only one instance, regardless of how many objects of the class are created static consts must be initialized when they are defined (all other data members must be initialized in the constructor or in other member functions) Run-time constants in classes Use the constructor initializer list. This means each object of this class can have a different constant value
QUIZ Is the destructor called in the right place in this code? Explain!
Yes! Although the destructor is called when the object (f) ends its lifetime, for a static object the lifetime is the entire program!
Ch. 9: Inline functions
Two problems w/preprocessor macros in C++ 1. A macro looks like a function call, but doesn t always act like one. This can create difficult-to-find bugs. This is also true with C 2. Specific to C++: the preprocessor has no permission to access class member data preprocessor macros cannot be used as class member functions. Review the example at beginning of ch.4 notes. More examples on the next slides.
QUIZ What does the preprocessor produce when given this code?
solution What does the preprocessor produce when given this code?
QUIZ What does the preprocessor produce when given this code?
solution What does the preprocessor produce when given this code? The preprocessor is smart enough to recognize strings and not mess with them!
Function-like macros The first rule: never separate the name of the macro from the opening parenthesis No space here!
Expressions may expand inside the macro so that their evaluation precedence is different from what you expect & has less precedence than >=
The problem can be corrected with a little work, but it s unintuitive, and, therefore, error-prone:
QUIZ What does the preprocessor produce when given this code? #define SQUARE(x) x*x SQUARE(2+3)
solution What does the preprocessor produce when given this code? #define SQUARE(x) x*x SQUARE(2+3) 2+3*2+3 11
Even if we do parenthesize the macro correctly, we still have the problem of side-effects: If we apply side-effects to the argument, they will be applied in each point of occurrence (unlike a function, where they only apply once!):...... See full code in text: C09:MacroSideEffects.cpp
A detailed classification of all possible macro-related bugs in C, with examples and explanations can be found at: https://gcc.gnu.org/onlinedocs/gcc-3.0.1/cpp_3.html#sec26
In C++ we have the following new problem: A macro has no concept of the scoping required with member functions:
C++ macro problem: a macro has no concept of the scoping required with member functions Someone wrote this on a forum: What will the code look like when the preprocessor is through? What is the correct way to implement what the programmer wants? Source: https://social.msdn.microsoft.com/forums/vstudio/en-us/607b89fe-10e6-49ca-866d-15aa2047f8c2/define-inside-a-class
C++ macro problem: a macro has no concept of the scoping required with member functions Someone wrote this on a forum: Source: https://social.msdn.microsoft.com/forums/vstudio/en-us/607b89fe-10e6-49ca-866d-15aa2047f8c2/define-inside-a-class
Solution to the C++ macro problem: C++ implements the macro in the compiler, as inline function, which is a true function in every sense. The only difference is that an inline function is expanded in place, like a preprocessor macro, so the overhead of the function call is eliminated.
When the compiler sees such a definition, it puts the function type (the signature combined with the return value) and the function body in its symbol table.
When the compiler later encounters calls to the function, it checks to ensure that the call is correct and that the return value is being used correctly then substitutes the function body for the function call, thus eliminating the overhead.
The inline code does occupy extra space, but, if the function is small, this space can actually be less than the code generated to do an ordinary function call (pushing arguments on the stack and doing the CALL).
Remember the rule many declarations, but only one definition, a.k.a. ODR? For the inline mechanism to work, we must include the header file containing the function declaration and its definition in every file* where the function is used. The compiler makes an exception so we don t end up with multiple definition errors. Of course, all definitions must be identical! * Technically, every translation unit.
Inlines inside classes The inline keyword is not needed inside a class definition. Any function defined inside a class definition is automatically an inline: example on next slide
Example: Both constructors and print function are inline
One of the most important uses of inline inside classes is the access function = small function that reads or changes the state of an object (one or more internal variables). example on next slide
The concept of access functions is further divided into: accessors, a.k.a. getters (to read state information from an object) mutators, a.k.a. setters (to change the state of an object).
In addition, overloading may be used to give the same name to both accessor and mutator: Note the naming problem! That s why a better way is
For complex examples with accessors and mutators, read: C09:Cpptime Stash and Stack with inlines
Inlines & the compiler What the compiler stores in its symbol table for an inline function: Entire prototype Function body (code)
Two cases in which the compiler may ignore the inline directive Function is too complicated (Depends on compiler) E.g. if function contains a loop Function address is taken (implicitly or explicitly [?]) Author means to say that function is accessed via function pointer, e.g.
How the compiler resolves fwd. references in inline functions No inline functions in a class is evaluated until the closing brace of the class declaration!
SKIP the remainder of Ch.9: Hidden activities in constructors & destructors Reducing clutter More preprocessor features Improved error checking No homework for ch. 9 EOL 1