Coding standards¶
- General Object-Oriented design principles you should try to follow:
- Identify the aspects of your application that vary and separate them from what stays the same;
- Program to an interface, not an implementation;
- Favor composition over inheritance;
- Strive for loosely coupled designs between objects that interact;
- Classes should be open for extension, but closed for modification;
- Depend upon abstractions. Do not depend upon concrete classes;
- Principle of Least Knowledge. Talk only to your immediate friends;
Including header files¶
Do not include header files unnecessarily. Even if PCMSolver is not a big project, unnecessary include directives and/or forward declarations introduce nasty interdependencies among different parts of the code. This reflects mainly in longer compilation times, but also in uglier looking code (see also the discussion in [Sut99]).
- Follow these guidelines to decide whether to include or forward declare:
- class A makes no reference to class B. Neither include nor forward declare B;
- class A refers to class B as a friend. Neither include nor forward declare B;
- class A contains a pointer/reference to a class B object. Forward declare B;
- class A contains functions with a class B object (value/pointer/reference) as parameter/return value. Forward declare B;
- class A is derived from class B. include B;
- class A contains a class B object. include B.
#ifndef MYCLASS_HPP
#define MYCLASS_HPP
//==============================
// Forward declared dependencies
class Foo;
class Bar;
//==============================
// Included dependencies
#include <vector>
#include "Parent.hpp"
//==============================
// The actual class
class MyClass : public Parent // Parent object, so #include "Parent.h"
{
public:
std::vector<int> avector; // vector object, so #include <vector>
Foo * foo; // Foo pointer, so forward declare
void Func(Bar & bar); // Bar reference as parameter, so forward declare
friend class MyFriend; // friend declaration is not a dependency
// don't do anything about MyFriend
};
#endif // MYCLASS_HPP
Proper overloading of operator<<¶
Suppose we have an inheritance hierarchy made of an abstract base class, Base, and two derived classes, Derived1 and Derived2. In the Base class header file we will define a pure virtual private function printObject and provide a public friend overload of operator<<:
#include <iosfwd>
class Base
{
public:
// All your other very fancy public members
friend std::ostream & operator<<(std::ostream & os, Base & base)
{
return base.printObject(os);
}
protected:
// All your other very fancy protected members
private:
// All your other very fancy private members
virtual std::ostream & printObject(std::ostream & os) = 0;
}
The printObject method can also be made (impure) virtual, it really depends on your class hierarchy. Derived1 and Derived2 header files will provide a public friend overload of operator<< (friendliness isn’t inherited, transitive or reciprocal) and an override for the printObject method:
#include <iosfwd>
#include "Base.hpp"
class Derived1 : public Base
{
public:
// All your other very fancy public members
friend std::ostream & operator<<(std::ostream & os, Derived1 & derived)
{
return derived.printObject(os);
}
protected:
// All your other very fancy protected members
private:
// All your other very fancy private members
virtual std::ostream & printObject(std::ostream & os);
}
class Derived2 : public Base
{
public:
// All your other very fancy public members
friend std::ostream & operator<<(std::ostream & os, Derived2 & derived)
{
return derived.printObject(os);
}
protected:
// All your other very fancy protected members
private:
// All your other very fancy private members
virtual std::ostream & printObject(std::ostream & os);
}
Code formatting¶
We conform to the so-called Linux (aka kernel) formatting style for C/C++ code (see http://en.wikipedia.org/wiki/Indent_style#Kernel_style) with minimal modifications. If uncertain on your code formatting use the Artistic Style command-line utility to rectify it:
astyle --style=linux --max-code-length=85 --indent-namespaces --keep-one-line-blocks filename