|
|
|
|
Compile-time constants in classes
The above use of const is
interesting and probably useful in cases, but it does not solve the original
problem which is: “how do you make a compile-time constant inside a
class?” The answer requires the use of an additional keyword which will
not be fully introduced until Chapter 10: static. The static
keyword, in this situation, means “there’s only one instance,
regardless of how many objects of the class are created,” which is
precisely what we need here: a member of a class which is constant, and which
cannot change from one object of the class to another. Thus, a
static const of a built-in type can be treated as
a compile-time constant.
There is one feature of static
const when used inside classes which is a bit unusual: you must provide the
initializer at the point of definition of the static
const. This is something that only occurs with the static const; as
much as you might like to use it in other situations it won’t work because
all other data members must be initialized in the constructor or in other member
functions.
Here’s an example that shows the
creation and use of a static const called size inside a class that
represents a stack of string
pointers[44]:
//: C08:StringStack.cpp
// Using static const to create a
// compile-time constant inside a class
#include <string>
#include <iostream>
using namespace std;
class StringStack {
static const int size = 100;
const string* stack[size];
int index;
public:
StringStack();
void push(const string* s);
const string* pop();
};
StringStack::StringStack() : index(0) {
memset(stack, 0, size * sizeof(string*));
}
void StringStack::push(const string* s) {
if(index < size)
stack[index++] = s;
}
const string* StringStack::pop() {
if(index > 0) {
const string* rv = stack[--index];
stack[index] = 0;
return rv;
}
return 0;
}
string iceCream[] = {
"pralines & cream",
"fudge ripple",
"jamocha almond fudge",
"wild mountain blackberry",
"raspberry sorbet",
"lemon swirl",
"rocky road",
"deep chocolate fudge"
};
const int iCsz =
sizeof iceCream / sizeof *iceCream;
int main() {
StringStack ss;
for(int i = 0; i < iCsz; i++)
ss.push(&iceCream[i]);
const string* cp;
while((cp = ss.pop()) != 0)
cout << *cp << endl;
} ///:~
Since size is used to determine
the size of the array stack, it is indeed a compile-time constant, but
one that is hidden inside the class.
Notice that push( ) takes a
const string* as an argument, pop( ) returns a
const string*, and StringStack holds const string*.
If this were not true, you couldn’t use a StringStack to hold the
pointers in iceCream. However, it also prevents you from doing anything
that will change the objects contained by StringStack. Of course, not all
containers are designed with this restriction.
|
|
|