This page contains various rules which anyone working on OpenCOR should (try to) respect. These rules were taken (paraphrased, if not simply copied/pasted) from the coding style document written by the developers of Qt Creator.
The following guidelines exist to make the code faster, clearer, and/or to take advantage of the strong type checking in C++.
++i; --j;
i++; j--;
Container::iterator end = large.end(); for (Container::iterator iter = large.begin(); iter != end; ++iter) { ... }
for (Container::iterator iter = large.begin(); iter != large.end(); ++iter) { ... }
foreach
loop in non-time-critical code with a Qt container. It is a nice way to keep line noise down and to give the loop variable a proper name:
foreach (QWidget *widget, container) doSomething(widget);
Container::iterator end = container.end(); for (Container::iterator iter = container.begin(); iter != end; ++iter) doSomething(*iter);Make the loop variable
const
, if possible. This might prevent unnecessary detaching of shared data.
foreach (const QString &name, someListOfNames) doSomething(name);
foreach (QString name, someListOfNames) doSomething(name);
int width; int height; char *nameOfThis; char *nameOfThat;
int a, b; char *c, *d;
class MainWindow : public QMainWindow { ... int mMyVariable; ... void myFunction(); ... }
class mainWindow : public QMainWindow { ... int Myvariable; ... void My_function(); ... }Note: class variables start with a lower-case
m
.
p
, but not local variables.
int main(int pArgc, char *pArgv[]) { int someVariable; ... }
int main(int argc, char *argv[]) { int pSomeVariable; ... }
public
, protected
and private
. The public
section is interesting for every user of the class. The private
section is only of interest for the implementors of the class (you).static
member.a
, rbarr
, nughdeget
) whenever possible. Use single-character variable names only for counters and temporaries where the purpose of the variable is obvious.int a; int b;
int a, b;This is especially important when initialisation is done at the same time:
QString a = "Joe"; QString b = "Foo";
QString a = "Joe", b = "Foo";Note:
QString a = "Joe";
is formally calling a copy constructor on a temporary string constructed from a string literal and therefore has the potential of being more expensive than direct construction by QString a("joe")
. However, the compiler is allowed to elide the copy (even if it had side effects), and modern compilers typically do so. Given these equal costs, OpenCOR code favours the =
idiom as it is in line with the traditional C-style initialisation, and cannot be mistaken as a function declaration, and reduces the level of nested parantheses in more initialisations.
char *p = "flop"; char &c = *p;
char* p = "flop"; char & c = * p;Also, we will have:
const char *p;
char const * p;Using a plain
0
for NULL
pointer constants is always correct and least effort to type. So:
void *p = 0;
void *p = NULL; void *p = '\0'; void *p = 42-7*6;Note: as an exception, imported third-party code can use
NULL
.
==
is part of the function name, and therefore, spaces make the declaration look like an expression:
operator==(type)
operator == (type)
void mangle()
void mangle ()
if (foo) { }
if(foo){ }
*
or &
, but never after.
int *a; int &b;
int* a; int& b;
char *blockOfMemory = (char *) malloc(data.size()); char *blockOfMemory = reinterpret_cast<char *>(malloc(data.size()));
char* blockOfMemory = (char* ) malloc(data.size());Of course, in this particular case, using
new
might be an even better option.
if (codec) { }
if (codec) { }Exception: function implementations and class declarations always have the left curly brace in the beginning of a line:
static void foo(int g) { qDebug("foo: %i", g); }
static void foo(int g) { qDebug("foo: %i", g); }
class Moo { };
class Moo { };
if (address.isEmpty()) return false;
if (address.isEmpty()) { return false; }
for (int i = 0; i < 10; ++i) qDebug("%i", i);
for (int i = 0; i < 10; ++i) { qDebug("%i", i); }Exception #1: use braces also if the parent statement covers several lines or if it wraps:
if ( address.isEmpty() || !isValid() || !codec) { return false; }
if ( address.isEmpty() || !isValid() || !codec) return false;Exception #2: use braces also in
if-then-else
blocks where either the if
code or the else
code covers several lines:
if (address.isEmpty()) { --it; } else { qDebug("%s", qPrintable(address)); ++it; }
if (address.isEmpty()) --it; else { qDebug("%s", qPrintable(address)); ++it; }
if (a) { if (b) ... else ... }
if (a) if (b) ... else ...
while (a) {}
while (a);
if ((a && b) || c)
if (a && b || c)
(a+b) & c
a+b & c
Tools|Options...
menu, then the Text Editor
section, and finally the Display
tab under the Text Wrapping
group box.
if ( longExpression || otherLongExpression || otherOtherLongExpression) { }
if (longExpression || otherLongExpression || otherOtherLongExpression) { }
typeinfo struct
, the dynamic_cast
or the typeid
operators, including throwing exceptions), unless you know what you are doing.man ascii
if unsure). For strings, use \\nnn
(where nnn
is the octal representation of whatever locale you want your string in) or \xnn
(where nn
is the hexadecimal representation):
QString s = QString::fromUtf8("\\213\\005");
QObject
:
QObject
subclass must have a Q_OBJECT
macro, even if it does not have signals or slots, if it is intended to be used with qobject_cast<>
.#include <QCoreApplication> #include <QMessageBox> #include <QSettings>
#include <QSettings> #include <QCoreApplication> #include <QMessageBox>
#include "common.h" #include "utils.h" #include <QCoreApplication> #include <QFileInfo> #include <QxtCommandOptions> #include <iostream>
<>
rather than ""
to make it easier to spot external dependencies in the sources.
#include <QxtCommandOptions>
#include "QxtCommandOptions"
#include <QFileInfo>
#include <QCore/QFileInfo>
static_cast
, const_cast
, reinterpret_cast
) Both reinterpret_cast
and C-style casts are dangerous, but at least reinterpret_cast
will not remove the const modifier.dynamic_cast
, use qobject_cast
for QObject
, or refactor your design, for example by introducing a type()
method (see QListWidgetItem
), unless you know what you are doing.QString s; return condition?s:"nothing"; // Crash at runtime - QString vs const char *
const char *
is cast to a const int *
, it will crash on machines where integers have to be aligned at two-byte or four-byte boundaries. Use a union to force the compiler to align variables correctly. In the example below, you can be sure that all instances of AlignHelper
are aligned at integer-boundaries:
union AlignHelper { char c; int i; };
main()
or not at all). Even if the execution time of the initialiser is defined for shared libraries, you will get into trouble when moving that code in a plugin or if the library is compiled statically:
// The default constructor needs to be run to initialize x static const QString x; // The constructor that takes a const char * has to be run static const QString y = "Hello"; // The call time of foo() is undefined and might not be called at all static const int i = foo();Things you can do:
// No constructor must be run, x is set at compile time static const char x[] = "someText"; // y will be set at compile time static int y = 7; // s will be initialised statically, i.e. no code is run static MyStruct s = {1, 2, 3}; // Pointers to objects are OK, no code needs to be run to initialise ptr static QString *ptr = 0; // Use Q_GLOBAL_STATIC to create static global objects instead Q_STATIC_GLOBAL(QString, s) void foo() { s()->append("moo"); }Note: static objects in function scope are not a problem. The constructor will be run the first time the function is entered. The code is not re-entrant, though.
char
is signed or unsigned, depending on the architecture. Use signed char
or uchar
if you explicitely want a signed or unsigned char. The following code will break on PowerPC, for example:
// The condition is always true on platforms where the default is unsigned if (c >= 0) { ... }
const
and non-const
iterators. This will silently crash on broken compilers.
for (Container::const_iterator it = c.constBegin(); it != c.constEnd(); ++it)
for (Container::const_iterator it = c.begin(); it != c.end(); ++it)
A
has class Q_EXPORT X: public QList<QVariant> {};
and library B
has class Q_EXPORT Y: public QList<QVariant> {};
. Suddenly, QList
symbols are exported from two libraries which results in a clash.
.cpp
file, not in its corresponding header file. There is a reason for having both a .cpp
file and a .h
file.enum
to define constants over static const int
or #define
. Enumeration values will be replaced by the compiler at compile time, resulting in faster code. Also, #define
is not namespace safe.inline
functions. It is probably better to rely on the compiler to optimise the code, if necessary, not to mention that, if badly used, inline
functions can result in slower code. A couple of good resources on the topic can be found here and here.a = 0.5*b;
a = b/2.0;
void myFunction(int &pMyVar) { pMyVar = 3; }
void myFunction(int *pMyVar) { *pMyVar = 3; }
int myFunction(const int &pMyVar) { return 3*pMyVar; }
void myFunction(int pMyVar) { return 3*pMyVar; }