## Class headers Each class or structure definition should be preceeded by a comment giving a brief description of the object, and its original author. The comment should conform to the following format : ``` /// \file Vector.h /// \brief encapsulates a 4d Homogenous Point / Vector object /// \author Jonathan Macey /// \version 3.0 /// \date 28/9/09 Updated to NCCA Coding standard /// Revision History : /// Initial Version 24/11/04 /// \todo lots of tidying up and code optimizations ``` # Member variables All member variables should use the following prefixes : ``` m_ : Standard member c_ : Constant s_ : Static member ``` These make it clear that the variable is a member of class or struct, and give some information about its usage. For ease of debugging, the object variable in a singleton class should always be named s_this. ## Variable and function declarations The class should be declared in the following order, unless there are practical reasons why this cannot be done ``` Public member variables Public member functions Protected member variables Private member variables Protected member functions Private member functions ``` Where possible, indent the names of class variables and class methods to make columns. The variable type or method return type is in the first column, and the variable name or method name is in the second column. The * of a pointer is in the first column because it improves readability when considered part of the type. This makes it easier to read the header as a list of functions and variables. Never define multiple variables using comma declaration lists.</p> Example : ``` class TempClass { public: TempClass(); ~TempClass(); // make all classes protected to allow inheritance // private should only be used if absolutly needed protected: int m_number; float m_real; ngl::Vector *m_device; std::string m_text; }; ``` ## Virtual functions With a complex class inheritance structure, it can be very difficult to understand how the methods of various classes interact with each other. One way to lighten the load of code maintenance is to be able to see if a function is virtual, and if so to which base class it belongs. <p>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: </p> ``` 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</h2> 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.</p> 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.</p> This is ok : ``` float randomVariable ``` This is not : ``` float RandomVariable ``` ## Use of const</h2> 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. [an error occurred while processing this directive]