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.