Table of Contents
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