TITLE: Prefer compile-time and link-time errors to runtime errors (This example taken from "Effective C++" by Scott Meyers, p. 175-178.) As defined in the ARM ..., there is no such thing as a mandatory runtime error in C++. No detection of division by zero, no checking for array bounds violations, nothing of that kind. Once your program gets through the compiler and linker, you're on your own -- there's no safety net. ... Whenever you can, push the detection of an error back from runtime to link-time, or, ideally, to compile-time. Such a methodology pays dividends not only in terms of program size and speed, but also in terms of reliability. If your program gets through the compiler and linker without eliciting any error messages, you know that there aren't any compiler- or linker-detectable errors in your program, period. (The other possibility, or course, is that there are bugs in your compiler...). With runtime errors, the situation is very different... You can test your program till you're blue in the face, but you'll still never cover all the possibilities... Often by making relatively minor changes to your design, you can catch during compilation what might otherwise be a runtime error. This frequently involves the addition of new types to the program. For example, suppose that you are writing a class to represent dates in time. Your first cut might look like this: class Date { public: Date (short day, short month, long year); ... }; [a better approach would be] enum Month { Jan, Feb, Mar, ..., Nov, Dec }; class Date { public: Date (short day, Month month, long year); ... }; Unfortunately, this doesn't buy you that much, because enums don't have to be initialized: Month m; Date d (22, m, 1857); // m is undefined As a result the date constructor would still have to validate the value of the month parameter. To achieve enough security to dispense with runtime checks, you've got to use a class to represent months, and you must ensure that only valid months are created: class Date { public: class Month { friend class Date; private: const unsigned short monthNumber; Month (short number) : monthNumber(number) {} }; Date (short day, Month month, long year); static const Month Jan, Feb, ..., Nov, Dec; }; const Date::Month Date::Jan(1); const Date::Month Date::Feb(2); ... const Date::Month Date::Dec(12); ... Because the Month objects are statics inside Date, a date must be declared like this: Date d (22, Date::Apr, 1857); // month name is fully qualified This is ugly, but this ugliness can be hidden by the clever use of global references... const Date::Month& Jan = Date::Jan; const Date::Month& Feb = Date::Feb; ... const Date::Month& Dec = Date::Dec;