Prefer const, enums, and inlines to #defines
#define ASPECT_RATIO 1.653 // 1. Never been seen by compilers, removed by the preprocessor // 2. ASPECT_RATIO not get entered into the symbol table // 3. Multiple copies of 1.653 in object code by preprocessor const double AspectRatio = 1.653; // 1. Seen by compilers // 2. Get entered into the symbol table // 3. Smaller code: never result in more than one copy // 4. No storage for const objects of integral types, unless create a pointer or ref const char * const strName = "Gary Hsieh"; // const pointer to const char #include <string> const std::string stdStrName = "Gary Hsieh"; // std::string object are generally preferable to char*-based progenitor. /* About class-specific constants */ class GamePlayer { private: static const int NumTurns = 5; // 1. A declaration, not a definition // 2. Usally need a definition, constant that are static and of integral type(e.g., int, bool, char) are an exception // 3. If not take address, can provide no definition int scores[NumTurns]; }; const int GamePlayer::NumTurns; // 1. Need address or compiler incorrectly insist on a definition // 2. Put in implementation file // 3. No initial value is permitted, because declaration has one class DefineInClass { int wrong[SOME_NUM]; // compiler error private: #define SOME_NUM 123 // 1. #define don't respect scope: if defined, will be in force for the rest of the compilation // 2. no private define int correct[SOME_NUM]; }; class CostEstimate { private: static const double FudgeFactor; }; const double CostEstimate::FudgeFactor = 1.35; // For compilers don't accept the syntax above /* Enum Hack */ class GamePlayer { private: enum { NumTurns = 5 }; int scores[NumTurns]; // If compilers insist knowing NumTurns and declaration with initial value is not accepted }; // 1. Behave like #define: can not take address // 2. No unnecessary memory allocation // 3. Lots of code employs it and a fundamental technique of template metaprogramming /* Macros -> functions */ #define CALL_WITH_MAX(a,b) isdigit((a) > (b) ? (a) : (b)) // 1. Don't incur the overhead of a function call // 2. Remember to parenthesize int a = 5, b = 0; bool x = CALL_WITH_MAX(++a, b); // a is incremented twice bool y = CALL_WITH_MAX(++a, b + 10); // a is incremented once template<typename T> inline void callWithMax(const T& a, const T& b) { isdigit(a > b ? a : b); } // 1. Template for an inline function // 2. Efficiency of a macro, predictable behavior(no need to parenthesize), type safety // 3. Obeys scope and access rules, e.g., private in a class
沒有留言:
張貼留言