Wednesday, March 5, 2008

C++: Class Constants vs. Defines

In C, one might do this...

struct Sam {
  unsigned char  flags;
  #define SAM_FIN  0x01
   #define SAM_SYN   0x02
   #define SAM_RST   0x04
   ...
};

struct Sam sam;
sam.flags = SAM_FIN && SAM_RST;

The intent of code like this is to imply that flags can take on only those defined values. However, the scope of the #defines is not limited to the structure, so name mangling must be used with it's attendant possibility of a collision. Worse, a client program might redefine one of these, with nary a peep from the compiler, resulting in undefined behavior.

In C++, the intent can be achieved much more gracefully like this...

class Sam {
public:
   unsigned char   flags;
   static const char   FIN = 0x01;
   static const char   SYN = 0x02;
   static const char   RST = 0x04;
   ...
};

Sam sam;
sam.flags = Sam::FIN && Sam::RST;

Because integer type static consts can be initialized in the body of the class, no external definition is required. Since the names are scoped to the class, there is no need for name mangling, and since they are constants, the client program cannot change them. All of the gains, none of the hassle.

Very cool.

No comments: