- Every class should have at least one constructor and a destructor even if it does nothing or is defined to do nothing. If a class does not have a constructor there is no guarantee of how objects of that class will be initialized, whilst data members should be explicitly initialized therein. When the constructor dynamically allocates memory, a destructor must be added to return the memory to the free pool when an object gets cleaned up.
- Each class should have an assignment operator:
ClassName& operator=(const ClassName&)and a copy constructor:
ClassName(const ClassName&)when allocating subsidiary data structures on the heap or consume any other kind of shared resources.
The assignment operator is called when one instance of a class is assigned to another.
The copy constructor defines the behaviour of the class when it is passed by value as an argument, returned by value from a function, or used to initialize one instance with the value of another class instance. Defining this constructor, all the class objects are copied properly. When it doesn't make sense to copy or assign instances of a given class, the copy constructor or the = operator should be made private.
- Data members should be made private/protected and accessed by inline functions in order to best implement information-hiding. Inline expansion avoids the overhead of a function call and can result in large savings of CPU time expecially if applied to member functions supporting public access to private data (allowing the maximum data-hiding for a required performance).
- The use of global variables or functions should be avoided where possible, in order to respect encapsulation.
- The use of friend classes should be avoided where possible. To garantee the encapsulation of a base class is always preferable to use protected data over friends or public data and then use inheritance.
- The use of type casting should be avoided. Especially from const* or const, type casting may be dangerous for data-hiding. In addition pointers should not be cast to int for portability reasons.
- Hard-coded numbers within the code must be avoided for portability and maintainability reasons. The use of costants (const) is a valid solution.
- Instead of the raw C types, the G4 types should be used. For the basic numeric types (int, float, double, etc ...), different compilers and different platforms provide different value ranges. In order to assure portability, the use of G4int, G4float, G4double, which are base classes globally defined is preferable. G4 types implement the right generic type for a given architecture.