no definition required S f(); // ok, no definition required - this is a function declaration only! S s; // error, definition required sizeof(S); // error, definition required More than one definition In certain cases, there can be more than one definition of a type or a template. A program consisting of multiple header files and source files will typically have more than one definition of a type, but not more than one definition per translation unit. If a program contains more than one definition of a type, then each definition must be equivalent. Definitions of static const data members In pre-standard C++, all static data members required a definition outside of their class. However, during the C++ standardization process it was decided to lift this requirement for static const integral members. The intent was to allow uses such as: struct C { static const int N = 10; }; char data[C::N]; // N "used" without out-of-class definition without a namespace scope definition for N. Nevertheless, the wording of the 1998 C++ standard still required a definition if the member was used in the program. This included the member appearing anywhere except as the operand to sizeof or typeid, effectively making the above ill-formed. This was identified as a defect, and the wording was adjusted to allow such a member to appear anywhere a constant expression is required, without requiring an out-of-class definition. This includes array bounds, case expressions, static member initializers, and nontype template arguments. struct C { static const int N = 10; static const int U = N; // Legal per C++03 }; char data[C::N]; // Legal per C++03 template<int> struct D; template<> struct D<C::N> {}; // Legal per C++03 However, using a static const integral member anywhere except where an integral constant-expression is required, requires a definition: struct C { static const int N = 10; }; int main() { int i = C::N; // Ill-formed in C++03. Definition of C::N required. } This requirement was relaxed in a later standard, C++11. Example showing unexpected side effects We need 4 files: "odr.h", "main.cpp", "odr1.cpp", "odr2.cpp" The acronym "odr" here is short for "One Definition Rule". odr.h: // abstract base class class CBase { public: virtual void xxx() = 0; virtual ~CBase() = default; }; extern CBase *odr1_create(); extern CBase *odr2_create(); main.cpp #include "odr.h" int main(int argc, char **argv) { CBase *o1 = odr1_create(); CBase *o2 =