The following rules help to achieve this: - All virtual methods must carry the virtual keyword, even though the C++ standard does not require this. - The first declaration of a virtual method should carry comments that describe its purpose. - If the purpose is self-evident, the comment should indicate why it is necessary for the method to be virtual. - Where a virtual method is overriden, it should be commented to indicate which class the method is first declared in. Example : ``` class BaseClass { public: // try to interpret this input, return false otherwise virtual bool HandleInput( Input const &_input ); }; class DerivedClass : public BaseClass { public: // from BaseClass virtual bool HandleInput( Input const &_input ); }; ``` ## Non-Virtual Functions Avoid hiding a base-class function in a derived class. Declaring a non-virtual function with the same name as a base class function will *hide* all the base class functions with that name. Overloading only works in the same naming scope, you can't add an overload in a derived class. ## Operator Overloads Operator overloading should only be used where it aids code readability, and the semantics are natural, obvious and intuitive. The semantics of the overload function should mirror the properties of the function when applied to fundamental types. Casting operators should only be used where the target type is conceptualy the same as the source type. This can otherwise cause the code to implicitly cast parameters to functions which take different types, leading to ambiguity. So, its ok for string to auto-cast to a char*, but having Vector3 auto-cast to a Vector4 is bad. ## Protection Classes that cannot be copied safely should protect against this by declaring private '=' operators, and private copy constructors. With C++ 11 we can use the keyword ```=delete`` For Example : ``` private: SomeClass ( SomeClass const& ); // DO NOT IMPLEMENT SomeClass& operator=( SomeClass const& ); // DO NOT IMPLEMENT ``` C++ 11 ``` private: SomeClass ( SomeClass const& )=delete; // DO NOT IMPLEMENT SomeClass& operator=( SomeClass const& )=delete; // DO NOT IMPLEMENT ``` If you don't want your class to have any virtual functions, explicitly declare your destructor non-virtual and make it private to prevent any inheritance from the class. This is only possible for classes that use the Create/Destruct or AddRef/Release patterns. ## Function Names Function names have the first letter of the name in lower case then each world capitalised after that, with no underscores between words. For Example:
``` addEntry(); draw(); drawHull(); ``` Where possible, functions/methods that return a bool result should have a name that looks like a question, eg ``` isValid(); hasProtocol(); areParallel(); ``` Each function should be preceeded by a comment containing a brief description about the function (how it works, what it does) above the function body in the .cpp file. ## Parameters Each parameter variable is placed on its own line, indented with a 2-space tab. Avoid default arguments that require temporary construction of an unnamed temporary object, as this can cause significant performance issues. Function parameters are prefixed as follows to indicate their usage (input/output/input-output). The first character of the variable name itself is lower case, with the first letter of each subsequent word capitalised. he following parameter prefixes are to be used : ``` _ Input Only (ie. _SampleID) o_ Output Only (ie. o_Count) io_ Input/Output (ie. io_SampleCount) ``` All input only parameters (prefixed with '_') should also be marked as const so that the code can always assume that they contains the original values that were passed in unless standard types (int float etc) For example : ``` void rotAxes(ngl::Vec3& io_a, ngl::Vec3& io_b, const Real _angle) { } ``` Complex types (structs or classes) should never be explicitly passed by value. ## Class Constructors Where a class constructor has an initialisation list, the ':' is placed on the same line as the closing parameter bracket. Each entry in the list is then placed on a separate line, indented with a 1-space tab. The initialisation list is split into 2 columns, with the variable names in one, and the initial values in the other. For Example : ``` /// \brief copy ctor /// @param[in] _v the value to set Vector(const Vector& _v) : m_x(_v.m_x), m_y(_v.m_y), m_z(_v.m_z), m_w(_v.m_w){;} ``` ## Local Variable names The first letter of a local variable name is lower case, with the first letter of each subsequent word in upper case. This is ok : ``` float randomVariable ``` This is not : ``` float RandomVariable ``` ## Use of const Parameters that are passed by value or reference should always be marked as const. For example : ``` void setNumber( const int _number) { // ... } ``` This guarantees that they always retain the value that was passed in, reduces the 'creeping death of const' effect. It can also help the compiler optimiser to generate more efficient code in some cases.