Consider the read( ), for example. Without inlines, the code generated for the call to read( ) would include pushing this on the stack and making an assembly language CALL. With most machines, the size of this code would be larger than the code
created by the inline, and the execution time would certainly be longer.
Without inline functions, an efficiency-conscious class designer will be tempted to simply
make i a public member, eliminating the overhead by allowing the user to directly access i.
From a design standpoint, this is disastrous because i then becomes part of the public interface, which means the class designer can never change it. You’re stuck with an int called i. This is a problem because you may learn sometime later that it would be much more useful to represent the state information as a float rather than an int, but because int i is part of the public interface, you can’t change it. If, on the other hand, you’ve always used member
functions to read and change the state information of an object, you can modify the
underlying representation of the object to your heart’s content (and permanently remove from
your mind the idea that you are going to perfect your design before you code it and try it out).
Accessors and mutators
Some people further divide the concept of access functions into accessors (to read state information from an object) and mutators (to change the state of an object). In addition, function overloading may be used to provide the same function name for both the accessor
and mutator; how you call the function determines whether you’re reading or modifying state
information. Thus,
//: C09:Rectangle.cpp
// Accessors & mutators
class Rectangle {
int _width, _height;
public:
Rectangle(int w = 0, int h = 0)
: _width(w), _height(h) {}
int width() const { return _width; } // Read
Chapter 7: Inline Functions
275
void width(int w) { _width = w; } // Set
int height() const { return _height; } // Read
void height(int h) { _height = h; } // Set
};
int main() {
Rectangle r(19, 47);
// Change width & height:
r.height(2 * r.width());
r.width(2 * r.height());
} ///:~
The constructor uses the constructor initializer list (briefly introduced in Chapter XX and
covered fully in Chapter XX) to initialize the values of _width and _height (using the pseudoconstructor-call form for built-in types).
Since you cannot have member function names using the same identifiers as data members,
the data members are distinguished with a leading underscore (this way, the coding standard
described in Appendix A can be followed, whereby all variables and functions begin with
lowercase letters). Because this is a bit awkward, and because overloading this way might
seem confusing, you may choose instead to use “get” and “set” to indicate accessors and
mutators:
//: C09:Rectangle2.cpp
// Accessors & mutators with "get" and "set"
class Rectangle {
int width, height;
public:
Rectangle(int w = 0, int h = 0)
: width(w), height(h) {}
int getWidth() const { return width; }
void setWidth(int w) { width = w; }
int getHeight() const { return height; }
void setHeight(int h) { height = h; }
};
int main() {
Rectangle r(19, 47);
// Change width & height:
r.setHeight(2 * r.getWidth());
r.setWidth(2 * r.getHeight());
} ///:~
Chapter 7: Inline Functions
276
Of course, accessors and mutators don’t have to be simple pipelines to an internal variable.
Sometimes they can perform some sort of calculation. The following example uses the
Standard C library time functions to produce a simple Time class:
//: C09:Cpptime.h
// A simple time class
#ifndef CPPTIME_H
#define CPPTIME_H
#include <ctime>
#include <cstring>
class Time {
std::time_t t;
std::tm local;
char asciiRep[26];
unsigned char lflag, aflag;
void updateLocal() {
if(!lflag) {
local = *std::localtime(&t);
lflag++;
}
}
void updateAscii() {
if(!aflag) {
updateLocal();
std::strcpy(asciiRep,std::asctime(&local));
aflag++;
}
}
public:
Time() { mark(); }
void mark() {
lflag = aflag = 0;
std::time(&t);
}
const char* ascii() {
updateAscii();
return asciiRep;
}
// Difference in seconds:
int delta(Time* dt) const {