Convenção de Programação

Recomendações para programação em C++.
Baseado em “The Elements of C++ Style - T. Misfeldt, G. Bumgardner, A. Gray

Namespace

  • Usar sempre o namespace TerraLib
  • Usar sempre os namespaces externos explicitamente

Exemplo

namespace TerraLib
{
  ....
  std::string myString = getName();
  ....
}

Preprocessador

  • Use '#include “ … “’ for collocated header files and '#include <…>' for external header files
  • Place preprocessor include guard (macros associadas a arquivos include) in header files
  • Use #if. . #endif and #if def . . #endif instead of ”/* . . .*/” comments to hide blocks of code
  • Use macros sparingly
  • Do not use “#define” to define constants – declare static const variables instead

Example

#ifndef TE_CONNECTION_POOL_H
#define TE_CONNECTION_POOL_H
....
static const float TeMaxFloat = 3.4e37;
....
#endif // end TE_CONNECTION_POOL_H

Declarações

  • Use typedefs to simplify complicated type expressions
  • Create a zero-valued enumerator to indicate an uninitialized, invalid, unspecified or default state
  • Do not define enumerations using macros or integer constants
  • Declare enumerations within a namespace or class

Example

typedef std::pair<TeLine, double> TeLineLength;
typedef std::vector<lineLength> TeLineSizes;
 
enum TeSelectionMode
{
  TeSelectionModeDefault,	  //!< default selection
  TeSelectionModeTePointed,	  //!< object pointed
  TeSelectionModeTeQueried,	  //!< object queried
  TeSelectionModeTePointedQueried //!< object pointed and queried
}

Escopo

  • Declare for-loop iteration variables inside of for statements

Example

for (int i = 0; i < 10; i++)

Funções e Métodos

  • Use an enumeration instead of a Boolean to improve readability
  • Use an object pointer instead of a reference if a function stores a reference or pointer to the object
  • Accept objects by reference and primitive or pointer types by value
  • Pass enumerator values, not integer constants
  • Do not use void* in a public interface
  • Use inline functions instead of macros
  • Inline only the simplest of functions

Classes

  • Define small classes and small methods
  • Declare the access level of all members
  • Declare all member variables private
  • Avoid the use of friend declarations

Membros de Classes

  • Declare an explicit default constructor for added clarity
  • Always declare a copy constructor, assignment operator, and destructor if the class can be instantiated
  • Always implement a virtual destructor if your class may be subclassed
  • Make constructors protected to prohibit direct instantiation
  • Make constructors private to prohibit derivation
  • Declare a private operator new() to prohibit dynamic allocation
  • Declare a protected or private destructor to prohibit static or automatic allocation
  • Declare single-parameter constructors as explicit to avoid unexpected type conversions
  • Use default arguments to reduce the number of constructors
  • Do not overload non-virtual methods in subclasses
  • Declare virtual methods protected and call them from public non-virtual methods
  • Keep your functions “const-correct“
  • Use object pointers and references in class declarations

Operadores

  • Adhere to the natural semantics of operators
  • Do not overload operator&&() or operator||()
  • Invoke the superclass assignment operator(s) in the assignment operator of a subclass
  • Implement copy-safe and exception-safe assignment operators
  • Define binary operators outside of a class
  • Implement a Boolean operator in terms of its opposite

Templates

  • Use templates instead of macros to create parameterized code
  • Do not use const or volatile qualified types as template parameters

Exemplo

// Example of bad macro
#define MAX(a,b) ( ((a) > (b)) ? (a) : (b) )
 
// Use template instead
template<class T>
inline T max (const T& a, const T& b)
{
  return (a > b) ? a : b/
}

Segurança, Cast e Conversões de Tipos

  • Use C++ casting operators instead of C-style casts. Ex:
    short a = 2000;
    int b;
    b = (int) a;    // c-like cast notation - Ok only for fundamental data types
     
    double d = 3.14159265;
    int i = static_cast<int>(d); // No need for this cast
  • Avoid type casting and do not force others to use it.
  • Use static-cast<> to impose non-intuitive implicit conversions
  • Do not use reinterpret-cast<> in portable code
  • Only use const-cast<> on “this” or when dealing with non-const-correct code
  • Never use dynamic-cast<> as a substitute for polymorphism
  • Use dynamic-cast<> to restore lost type information
  • Always treat string literals as const char*
  • Use C++ streams instead of stdio function for type safety. Exemplo:
    const char* myMessage = "Hello World!!!"; // A string literal
     
    printf("%s", myMessage); // Stdio function
    std::cout << myMessage << std::endl; // Use this instead
  • Test all type conversions

Inicialização e Construção

  • Initialize all variables
  • Do not rely on the order of initialization of global objects
  • Always construct objects in a valid state
  • Initialize member variables in the initializer list
  • Initialize member variables in the order they are declared
  • Indicate when the declaration order of data members is significant
  • Always list any superclass constructors in the initialize list of a subclass constructor
  • Do not call virtual functions in constructors and destructors
  • Declare and initialize static variables within functions
  • Zero pointers after deletion
  • Use the new and delete operators instead of malloc() and free()

Declarações e Expressões

  • Do not rely on operator precedence in complex expressions
  • Use block statements in control flow constructs
  • Do not test for equality with true
  • Replace repeated non-trivial expressions with equivalent methods
  • Use size-t variables for simple loop iteration and array subscripts
  • Use a dummy template function to eliminate warnings for unused variables

Fluxo de Controle

  • Avoid break and continue in iteration statements
  • Avoid multiple return statements in functions
  • Do not use goto
  • Do not use try .. throw .. catch to manage control flow
  • Never use setjmp() or longjmp() in a C++ program
  • Always code a break statement in the last case of a switch statement

Manipulação de Erros e Exceções

  • Use return codes to report unexpected state changes
  • Use assertions to enforce a programming contract
  • Do not silently absorb or ignore unexpected runtime errors
  • Use assertions to report unexpected or unhandled runtime errors
  • Use exceptions to report errors that may occur under normal program execution
  • Manage resources with RAII for exception safety
  • Catch exceptions by reference, not by value
  • Do not discard exception information if you throw a new exception within a catch block
  • Avoid throwing exceptions in destructors

Eficiência

  • Use lazy evaluation and initialization
  • Reuse objects to avoid reallocation
  • Leave optimization for last

Navigation