Thursday, January 5, 2012

the enum hack c++:


the enum hack c++:

It's often convenient to define class-specific constants, and that calls for a slightly different tack. To limit the scope of a constant to a class, you must make it a member, and to ensure there's at most one copy of the constant, you must make it a static member: 

class CricketPlayer {
   private:
      static const int INNINGS = 5;    // constant declaration
      int scores[INNINGS];             // use of constant
      ...
};

There's a minor wrinkle, however, which is that what you see above is a declaration for INNINGS, not a definition. You must still define static class members in an implementation file:

const int CricketPlayer::INNINGS;    // mandatory definition;
                                     // goes in class impl. file 

There's no need to lose sleep worrying about this detail. If you forget the definition, your linker should remind you.

Older compilers may not accept this syntax, because it used to be illegal to provide an initial value for a static class member at its point of declaration. Furthermore, in-class initialization is allowed only for integral types (e.g., ints, bools, chars, etc.), and only for constants. In cases where the above syntax can't be used, you put the initial value at the point of definition:

class EngineeringConstants {         // this goes in the class
   private:                          // header file
      static const double X_FACTOR;
      ...
};
// this goes in the class implementation file
const double EngineeringConstants::X_FACTOR = 1.35; 

This is all you need almost all the time. The only exception is when you need the value of a class constant during compilation of the class, such as in the declaration of the array  

CricketPlayer::scores

above (where compilers insist on knowing the size of the array during compilation). Then the accepted way to compensate for compilers that (incorrectly) forbid the in-class specification of initial values for integral class constants is to use what is affectionately known as "the enum hack" This technique takes advantage of the fact that the values of an enumerated type can be used where ints are expected, so CricketPlayer could just as well have been defined like this:

class CricketPlayer {
   private:
      enum { INNINGS = 5 };      // "the enum hack" — makes
                                 // INNINGS a symbolic name
                                 // for 5
      int scores[INNINGS];       // fine
      ...
};

Unless you're dealing with compilers of primarily historical interest (i.e., those written before 1995), you shouldn't have to use the enum hack. Still, it's worth knowing what it looks like, because it's not uncommon to encounter it in code dating back to those early, simpler times.

No comments:

Post a Comment