User Tools

Site Tools


coding_style

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
coding_style [2016/03/02 06:01] – [Style] jmgrcoding_style [2023/04/25 16:52] (current) – external edit 127.0.0.1
Line 1: Line 1:
-====== Best Practices ======+====== Coding Style ======
  
-===== General ======+===== Spaces vs Tabs ===== 
 +Qt Creator uses spaces for indentation. Since we will probably be using Qt and since Qt Creator is the default IDE when writing code using Qt, **spaces** should be used for indentation.
  
-==== Tips & tricks ==== +===== Braces ===== 
- +Opening and closing braces should be on a new line, in most casesclasses, functions, namespaces, arrays, etc. The only exception would be initialization. 
-  * Always initialise primitive variables (other types do not require this) +<code cpp> 
- +namespace MyNamespace
-<sxh cpp> +
-// Bad +
-int myVariable; +
-std::string myString; +
-// Good +
-int myVariable{}; +
-std::string myString; +
-</sxh> +
- +
-  * Always set parameters as const reference if they are non-primitives +
- +
-<sxh cpp> +
-// Bad +
-void myFunction(int firstParameter, std::string secondParameter)+
 { {
-  //...+    void MyFunction() 
 +    { 
 +        while(true) 
 +        { 
 +            int value{42}; 
 +        } 
 +    }
 } }
-// Good +</code>
-void myFunction(int firstParameter, const std::string &secondParameter) +
-+
-  //... +
-+
-</sxh>+
  
-  * Do not use "using namespace" outside of a function => improves readability (and only use it when needed)+===== Naming =====
  
-<sxh cpp> +^ Item ^ Example ^ Comment ^ 
-// Bad +| type (class/struct) | SomeExample | | 
-using namespace std;+| variable | someExample | | 
 +| member variable | m_someExample | | 
 +| global variables | gSomeExample | should be avoided | 
 +| function | someExample() | function names should begin with a verb: computeMap(), displayWindow() | 
 +| member function | someExample() | | 
 +| getter function | name() | not getName(), Qt convention | 
 +| setter function | setName() | | 
 +namespace | SomeExample | | 
 +| template parameter | SomeExample | |
  
-void myFunction() +**Never use abbreviations in names, having long names is not an issue: all IDEs have an auto-completion feature.** 
-+<code cpp>
-  string myString; +
-  //... +
-+
-// Good +
-void myFunction() +
-+
-  using namespace std; +
-   +
-  string myString; +
-  //... +
-+
-</sxh> +
- +
-  Use references instead of pointers if possible => easier to use (but note that Qt uses a lot of pointers for historical reasons) +
- +
-<sxh cpp>+
 // Bad // Bad
-void myFunction(MyObject *object)+void getNbApples()
 { {
-  object->function()+    int avgFuncSizePerAlloc = 42
-  //...+    //...
 } }
-// Good 
-void myFunction(MyObject &object) 
-{ 
-  object.function(); 
-  //... 
-} 
-</sxh> 
  
-  * Use smart pointers instead of raw/naked/dumb pointers => easier to use (but note that Qt uses its own memory management system, so if using Qt classes or Qt-based classes you will have to use //new// at least) 
- 
-<sxh cpp> 
-// Bad 
-MyObject *object = new MyObject; 
- 
-delete object; 
 // Good // Good
-#include <memory> +void getAppleCount()
- +
-std::unique_ptr<MyObject> object{std::make_unique<MyObject>()}; +
-// Good +
-#include <QObject> +
- +
-// parentObject is a pointer to a QObject +
- +
-MyObject *object = new MyObject(parentObject); +
-</sxh> +
- +
-  * If you have to write a function that returns multiple values, prefer returning a std::tuple instead of using reference parameters (if possible) +
- +
-<sxh cpp> +
-// Bad +
-void myFunction(int &outFirstVariable, std::string &outSecondVariable)+
 { {
-  outFirstVariable = 42; +    int averageFunctionSizePerAllocation = 42; 
-  outSecondVariable = "text";+    //...
 } }
-// Good +</code>
-#include <tuple> +
- +
-std::tuple<int, std::string> myFunction() +
-+
-  return std::make_tuple(42, "text"); +
-+
- +
-// auto result = myFunction(); +
-// Use std::get<0>(result) to get the integer, std::get<1>(result) to get the std::string +
-</sxh> +
- +
-  * When using events, prefer using lambdas (nameless functions) instead of static functions +
- +
-<sxh cpp> +
-#include <QPushButton> +
- +
-QPushButton *button = new QPushButton(parent);+
  
 +**Prefer using meaningful names instead of "one letter" names like i,j,k.**
 +<code cpp>
 // Bad // Bad
-void MyObject::onClick(+for(int i = 0; i < ducks.size(); ++i)
-+
-  //... +
-+
- +
-connect(button, SIGNAL(clicked()), this, SLOT(onClick())); +
- +
-// Good +
-connect(button, &QPushButton::clicked(), [this]() +
-+
-  //... +
-}); +
-</sxh> +
- +
-  * Never forward-declare variables +
- +
-<sxh cpp> +
-// Bad +
-int i+
-int j; +
- +
-for(; i < 10; ++i)+
 { {
-  for(; j < 10; ++j) 
-  { 
     //...     //...
-  } 
 } }
  
 // Good // Good
-for(int i{}10; ++i)+for(int duckIndex = 0duckIndex ducks.size(); ++duckIndex)
 { {
-  for(int j{}; j < 10; ++j) 
-  { 
     //...     //...
-  } 
 } }
-</sxh>+</code>
  
-  Write small functions instead of huge ones +**Variables representing GUI elements should be suffixed by their type** 
-  Never call virtual functions from a constructor: https://stackoverflow.com/questions/496440/c-virtual-function-from-constructor +<code cpp> 
-===== Qt specific ===== +// Bad 
- +QPushButton *exitApplication; 
-==== Containers ==== +QLabel *duckCount;
- +
-^ C++ Standard Library ^ Qt ^ +
-| [[http://en.cppreference.com/w/cpp/container/vector|std::vector]] | Contiguous memory bloc? Yes: [[https://doc.qt.io/qt-5/qvector.html|QVector]] No: [[https://doc.qt.io/qt-5/qlist.html|QList]]* | +
-| [[http://en.cppreference.com/w/cpp/container/list|std::list]] | [[https://doc.qt.io/qt-5/qlinkedlist.html|QLinkedList]] | +
-| [[http://en.cppreference.com/w/cpp/container/set|std::set]] | [[https://doc.qt.io/qt-5/qset.html|QSet]] | +
-| [[http://en.cppreference.com/w/cpp/container/map|std::map]] | [[https://doc.qt.io/qt-5/qmap.html|QMap]] | +
-| [[http://en.cppreference.com/w/cpp/container/unordered_map|std::unordered_map]] | [[https://doc.qt.io/qt-5/qhash.html|QHash]] | +
-| [[http://en.cppreference.com/w/cpp/container/multimap|std::multimap]] | [[https://doc.qt.io/qt-5/qmultimap.html|QMultiMap]] | +
-| [[http://en.cppreference.com/w/cpp/container/unordered_multimap|std::unordered_multimap]] | [[https://doc.qt.io/qt-5/qmultihash.html|QMultiHash]] | +
- +
-*If in doubt, use [[https://doc.qt.io/qt-5/qlist.html|QList]]. +
- +
-**/!\ [[http://en.cppreference.com/w/cpp/container/list|std::list]] is not equivalent to [[https://doc.qt.io/qt-5/qlist.html|QList]] /!\** +
- +
-Prefer using [[https://doc.qt.io/qt-5/qhash.html|QHash]] and [[https://doc.qt.io/qt-5/qmultihash.html|QMultiHash]] over [[https://doc.qt.io/qt-5/qmap.html|QMap]] and [[https://doc.qt.io/qt-5/qmultimap.html|QMultiMap]] if you don't need the items to be sorted, their lookup time is smaller. +
-==== Inheritance ==== +
- +
-QObject-based: +
- automatic memory management (no smart pointer required) +
- constructor takes a parent QObject, defaulted to nullptr +
- * Q_OBJECT macro at the beginning of the class +
- +
-<file cpp myobject.hpp+
-#pragma once +
- +
-#include <QObject> +
- +
-class MyObject: public QObject +
-+
-  Q_OBJECT +
-   +
-public: +
-  MyObject(QObject *parent = nullptr); +
-  virtual ~MyObject(); +
-+
-</file> +
- +
-<file cpp myobject.cpp> +
-#include "myobject.hpp" +
- +
-MyObject::MyObject(QObject *parent): +
-  QObject(parent) +
-+
-+
- +
-MyObject::~MyObject() +
-+
-+
-</file> +
- +
-QWidget-based: +
-automatic memory management (no smart pointer required) +
-constructor takes a parent QWidget, defaulted to nullptr +
- * Q_OBJECT macro at the beginning of the class +
- +
-<file cpp mywidget.hpp> +
-#pragma once +
- +
-#include <QWidget> +
- +
-class MyWidget: public QWidget +
-+
-  Q_OBJECT +
-   +
-public: +
-  MyClass(QWidget *parent = nullptr); +
-  virtual ~MyClass(); +
-+
-</file> +
- +
-<file cpp mywidget.cpp> +
-#include "mywidget.hpp" +
- +
-MyWidget::MyWidget(QWidget *parent): +
-  QWidget(parent) +
-+
-+
- +
-MyWidget::~MyWidget() +
-+
-+
-</file> +
- +
-Other classes: +
- * memory management through smart pointers +
- +
-====== Style ======+
  
 +// Good
 +QPushButton *exitApplicationPushButton;
 +QLabel *duckCountLabel;
 +</code>
 ===== Code files ===== ===== Code files =====
  
 ==== Code separation ==== ==== Code separation ====
  
-Generally speaking, each class/struct should have its declaration in one file (header) and its definition in another file (source file). If a class/struct is very small then it can be contained in a header, for example if it only contains variables and no functions. Qt specific: note that QObject/QWidget-based classes have to have their own header file in order to the MOC (Qt'meta compiler) to find them. +Generally speaking, each class/struct should have its declaration in one file (header) and its definition in another file (source file). If a class/struct is very small then it can be contained in a header, for example if it only contains variables and no functions. Qt specific: note that QObject/QWidget-based classes have to have their own header file in order to the [[http://doc.qt.io/qt-5/moc.html|moc]] (Qt'Meta-Object Compiler) to find them.
 ==== Naming ==== ==== Naming ====
  
Line 285: Line 110:
 This feature in implemented in all known compilers and is both easier to use and foolproof. It has not been accepted into the C++ standard because of some particular cases, like having source files on multiple "remote mounts": https://stackoverflow.com/questions/23696115/is-pragma-once-part-of-the-c11-standard. This feature in implemented in all known compilers and is both easier to use and foolproof. It has not been accepted into the C++ standard because of some particular cases, like having source files on multiple "remote mounts": https://stackoverflow.com/questions/23696115/is-pragma-once-part-of-the-c11-standard.
  
-====== Examples ====== 
  
-<code cpp> 
-#include <string> 
-#include <memory> 
- 
-// An entity semantic class 
-class MyExampleClass final 
-{ 
-public: 
-    // This constructor is explicit to prevent something like this: MyExampleClass test = "some text"; 
-    explicit MyExampleClass(const std::string &myString): 
-        m_myVar{52}, 
-        m_myString{myString} 
-    { 
-    } 
- 
-    // Entity semantic: always forbid copy & assignment 
-    MyExampleClass(const MyExampleClass &) = delete; 
-    MyExampleClass &operator=(const MyExampleClass &) = delete; 
- 
-private: 
-    // Variables are always at the end, because they represent an implementation detail 
-    int m_myVar{42}; 
-    std::string m_myString{"value"}; 
-}; 
- 
-// A value semantic class 
-class MyVector final // Always final: a value semantic class should *never* be inherited from 
-{ 
-public: 
-    // We want to use the default implementation (wich is faster than anything we can do) 
-    MyVector() = default; 
- 
-    MyVector(const MyVector &other): 
-        m_x(other.m_x), 
-        m_y(other.m_y) 
-    { 
-    } 
- 
-    MyVector &operator=(MyVector other) 
-    { 
-        std::swap(m_x, other.m_x); 
-        std::swap(m_y, other.m_y); 
- 
-        return *this; 
-    } 
- 
-private: 
-    // m_x and m_y are initialized with the default value for the type int: 0 
-    // unless the initializer list in a constructor decides otherwise 
-    int m_x{}; 
-    int m_y{}; 
-}; 
- 
-void test() 
-{ 
-    // I use scopes "{}" here to limit where my variables live and are accessible 
-    { 
-        // Allocation on the stack (fast) 
-        MyExampleClass myExampleClass{"some text"}; 
-        // myExampleClass is destroyed here 
-    } 
-    { 
-        // Allocation on the heap (slower, allows polymorphism) 
-        std::unique_ptr<MyExampleClass> myExampleClass{std::make_unique<MyExampleClass>("some text")}; 
-        // Or (with auto) 
-        auto myExampleClass{std::make_unique<MyExampleClass>("some text")}; 
-        // myExampleClass is destroyed here (thanks to the smart pointer) 
-    } 
-} 
-</code> 
coding_style.txt · Last modified: 2023/04/25 16:52 by 127.0.0.1