TICS Coding Standard Viewer 
TIOBE Software Quality Framework
Print-friendly version
©TIOBE Software www.tiobe.com
 
C++ Coding Standard
Search

Rule:  TT#014

Synopsis:Class Declarations
Language:C++
Severity Level:5
Category:Object Oriented Programming


Description:

Class declarations

There should only be one class (or one group of closely related classes) declaration per header file. E.g. a “tree” class with its corresponding “tree node” and “tree node iterator” classes can go into one file as long as the node and iterator classes are small and simple enough. If the classes are not closely related split them in different files.

In general the order of the elements of the class should be first public, then protected, then private. Follow this order unless it creates compilation problems (e.g. public interface ). Rationale: the users of the class are normally interested only in the public interface. Within each scope block all types, data and function members that are logically related should be grouped together.

Constructor declarations

Constructors with only one argument should be declared explicit. Also beware of constructors with multiple arguments if they accept default values. Rationale: in general it’s better to avoid implicit conversions as they can cause obscure bugs.

You should define a default constructor if your class defines member variables and has no other constructors, to make sure your members are always in a well defined state.

The same applies to copy constructors and assignment operators. For this reason, a class that should not be copyable (e.g. it might have a pointer to a privately owned buffer) should make the copy constructor and assignment private and leave them unimplemented.

class CShouldNotBeCopied
{
...
private:
  CShouldNotBeCopied(const CShouldNotBeCopied&); // Copying not allowed
  void operator = (const CShouldNotBeCopied&); // Copying not allowed
};

Consider the rule of the Big Three (see this Wikipedia link:): if a class defines one of the following it should probably explicitly define all three: destructor, copy constructor and copy assignment operator.

Member variables

Member variables should always be private (note: not protected). Add (inline) getters and setters. Use these getters and setters even in the owner class, because having a single access point for your variables helps to reduce the complexity of the code and is helpful during debugging (e.g. it allows to introduce logging statements to record when data is modified, etc).

The this pointer

Don’t use ‘this’ to access a member when it’s not necessary.

Class method declarations

Class methods should be declared following a logical order.

In every block (public, protected, private) the constructors precede the destructor, followed by the rest of the methods, and finally the member variables.

Inline methods

Define methods inline only if you need to, and only when they are small and simple, say, 10 lines or less (not a hard limit, use common sense).

In order to keep the interface clean inline methods longer than a couple of lines should be defined outside and below the class declaration using the inline keyword. Also when there are too many of them.

When the inline methods are defined within the class declaration the inline keyword is superfluous and should be avoided.

Avoid moving inline methods to a separate file (e.g. to a ‘.inl’ file). Rationale: the .inl extension is non-standard, non-obvious and not all the tools and editors support it, besides not being included in default search filters.

Virtual methods

If a method is virtual, any derived versions of the method in the derived classes should be declared virtual too. If you have a virtual method, make sure you also make the destructor virtual.

Constructor implementation

The implementation of a class constructor should have all possible initializations (base classes first, member variables second, all in order of declaration). Prefer initializer lists over setting values in the constructor body where possible (these allow the compiler to do some work under the hood).

CFineClass::CFineClass(int aValue) :
  CBaseClassA(),
  CBaseClassB(),
  iMember(aValue)
{
}

Arguments

In function declarations, all arguments must have a type and a name. Function argument names used in source files must exactly match the argument names in the declaration. Be consistent in the order of the arguments. Recommended order is: first only output, input/output and only input. In any case be consistent with the ordering of arguments in the whole class interface.

When there are no arguments do not use the keyword ‘void’.:

void DoThings(int& aOutVariable, int& aInOutVariable, int aInVariable);
void Copy(char* aDestination, const char* aSource, int aCount);
int CalculateDistance();

Return values

Always declare the return type of functions. Do not default to int.



Literature References:
TomTom Guidelines