// This file describes the coding guidelines for c++. // It file is best viewed by browsing the doxygen-generated documentation. // It appears under the the "Related Pages" tab. // Consult the README file for instructions on generating the documentation. /*! \page CppCodingGuidelines C++ Coding Guidelines The following guidelines are based on a draft document from Baudouin Raoult. \section files_extensions Files Extensions - Each class is defined in two files, the header file, that contains the class definition, with an extension of .h, and the implementation file with the extension .cc - The file names should match the name of the class. - .cc and .h files must be in the same directory. - A .h file should not include more than one class definition, except in the case of a factory class, which may be defined in the same file as the class it manufactures. \section header_files Header Files - Header files should follow the layout suggested in \link ExampleHeader Documents/ExampleHeader.h\endlink. - The public, protected and private sections of a class should be declared in that order (i.e. public first, private last). - Use \#include guards to protect against multiple inclusions. - Header files should not contain namespace using statements, since this causes the namespace to be "used" in any file that includes the header. \section code_documentation Code Documentation - Documentation is generated using doxygen. - Instructions on building the documentation are in the \link README README\endlink file. - The doxygen manual can be found here. - See here for instructions on including \f$\mbox{\LaTeX}\f$ mathematical formulae. - Doxygen recognises special comments: - A brief comment is a single line like this: \verbatim //! This one-line comment gives a brief description of a class or method.\endverbatim - A detailed comment looks like this: \verbatim /*! * This is a detailed comment. It has more than one line, * and provides more complete information about a class or method. */ \endverbatim - Class definitions should be preceded by a doxygen brief comment followed by a detailed comment. - Methods declarations and members should be preceded by a doxygen brief comment, unless the role of the method or member is completely obvious from its name. A detailed comment may also be provided. - Normal C++ comments should be used in .cc files where necessary to explain the internal logic of a function. - Don't include comments to indicate authorship or modification history. That is what git blame is for! - HTML links to auxilliary documents (e.g. pdf files) can be made to appear on the \link Overview Overview\endlink page by adding them to Documents/overview.h \section includes Includes Don't include unessesary headers. Use class forwarding. The compiler only needs to see a class definition when calling methods or establishing the size of an object. When refering to a pointer or a reference, the compiler does not need to know the detail of the class. \section identifiers Identifiers - Identifiers should be in lower case with an upper case letter at the start of each internal word: e.g. changeResolution - Class names should start with an upper case letter - Method and member names should start with a lower case letter - Member names have an underscore at the end - All other variables should be all lower case - Use short identifiers for local variables, loop indices, etc. - Use longer, meaningful names for methods, members, classes, etc. \section use_of_const Use of Const - Use const wherever possible. - Avoid passing objects by const value. Pass by const reference instead. - Remember. The rule when reading definitions is to work from right to left. So, for example, char * const test means that test is a const pointer to a char object: - const char * test = "xyz"; // non-const pointer to const data - char * const test = "xyz"; // const pointer to non-const data - const char * const test = "xyz"; // const pointer to const data - bool isEmpty() const; // the isEmpty method does not change its object. \section constructors_and_destructors Constructors and Destructors - Always declare copy and assignment constructors. Make them private unless you need to copy. - If the default copy constructor is sufficient, include a comment to this effect in the class definition. - Write the constructors and the destuctors at the same time. - If the class has a virtual table, its destructor must be virtual. - All resources allocated by an object must be deallocated in the destuctor. - Beware of partially constructed objects. - Except for the copy constructor, single-argument constructors should be declared explicit to prohibit implicit type conversions. - If you need copy, assignment or a destructor, then you probably need all three. - Base class destructors must be either public and virtual, or protected and not virtual. - The copy constructor should copy all the data. However, you may wish to give it a second, default argument to allow this behaviour to be over-ridden. - Note that MyClass a = b calls the copy constructor, not the assignment operator. \section members Member Variables - Member variables should always be private. - Use accessors if you need to access a member variable from outside a class. - Don't use the accessors from within the class. Use the member itself. \section accessors Accessors Accessors are short methods designed to access members. - Accessors should only be implemented if necessary (they break the encapsulation) - Accessors should be inline - Accessors must have the same name as the member (but without the underscore) \section Methods - A method is a request to an object to do something or to provide something. The name of the method should reflect this. - E.g. changeResolution is preferable to resolutionChanger. \section pointers Pointers and References - Prefer references to pointers. If an object is guaranteed to exist, use a reference. - Passing or returning an non-const pointer means passing ownership of the pointed object. - Passing or returning a const pointer means keeping ownership of the pointed object, and that the pointed object can be null - In any other case, pass a referece to the object. Use const whenever the object will not be modified. \section c_code C Code - Don't use C functions (e.g. printf) if C++ provides the same functionality. - Avoid using C style casts. - For unsigned value, use a typedef: typedef unsigned long ulong; \section preprocessor Preprocessor - The preprocessor should only be used to define \#include guards in .h files and for variables specified via the -D flag at compile time. - The preprocessor should not be used to define macros or constants. \section namespaces Namespaces - Model-independent code should be defined in the oops namespace. - Model-specific code should be defined outside the the oops namespace. - Do not use an entire namespace. In particular, do not use the statement: using namespace std; - Explicitly list the things you are using from other namespaces: - using std::cout; - using oops::Model; - etc. - using statements must never be used at global scope in a header file. - Use anonymous namespaces to restrict classes (e.g. Factories) to file scope. \section readability Readability - Indent class and function bodies, if and for blocks, etc. - The opening brace should appear - either: on the same line as the argument list, initialisation list, loop expression. etc. - or: on its own line, aligned with the start of the statement - The closing brace should appear on its own line, and aligned with the start of the statement it closes. - Keep lines below 80 characters. - Split long lines in a way that makes it obvious that the code continues on the next line. - Continuation lines should be indented. - If you split an argument list, align the arguments with those on the previous line. \section optimization Optimization - Pass objects by reference, not by value. - Prefer initialization over assignment. - Use ++i, not i++ when incrementing iterators. - Use the initialization list to initialize member objects. \section miscellaneous Miscellaneous - Make interfaces non-virtual. - Make virtual functions private. - Check for assignment to self in operator=. */