Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Thinking in C++
Prev Contents / Index Next

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.

Thinking in C++
Prev Contents / Index Next

 
 
   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire