forked from qt-creator/qt-creator
871 lines
26 KiB
Plaintext
871 lines
26 KiB
Plaintext
/****************************************************************************
|
||
**
|
||
** This file is part of Qt Creator
|
||
**
|
||
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||
**
|
||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||
**
|
||
** No Commercial Usage
|
||
**
|
||
** This file contains pre-release code and may not be distributed.
|
||
** You may use this file in accordance with the terms and conditions
|
||
** contained in the Technology Preview License Agreement accompanying
|
||
** this package.
|
||
**
|
||
** GNU Free Documentation License
|
||
**
|
||
** Alternatively, this file may be used under the terms of the GNU Free
|
||
** Documentation License version 1.3 as published by the Free Software
|
||
** Foundation and appearing in the file included in the packaging of this
|
||
** file.
|
||
**
|
||
** If you have questions regarding the use of this file, please contact
|
||
** Nokia at qt-info@nokia.com.
|
||
**
|
||
****************************************************************************/
|
||
|
||
/*!
|
||
|
||
\contentspage{index.html}{Qt Creator}
|
||
\page coding-style.html
|
||
|
||
\title Qt Creator Coding Rules
|
||
|
||
THIS IS PRELIMINARY.
|
||
|
||
\section1 Introduction
|
||
|
||
The aim of this section is to serve as a guide for the developers, to aid us
|
||
to build understandable and maintainable code, to create less confusion and
|
||
surprises when working on Qt Creator.
|
||
|
||
As usual: Rules are not set in stone. If there's a good reason to break one,
|
||
do it, preferably after making sure that there are others agreeing.
|
||
|
||
This document is incomplete.
|
||
|
||
In general, if you want to contribute to the main source, we expect at least
|
||
that you:
|
||
|
||
\list 1
|
||
\o The most important rule first: KISS (keep it simple ...): always
|
||
use a simple implementation in favor of a more complicated one.
|
||
This eases maintenance a lot.
|
||
\o Write good C++ code: Readable, well commented when necessary,
|
||
and taking advantage of the OO model. Follow the \l{Formatting} guidelines.
|
||
There are also certain \l{Code Constructs} that we try to follow.
|
||
\o Adapt the code to the structures already existing in Qt Creator, or in
|
||
the case that you have better ideas, discuss them with other developers
|
||
before writing the code.
|
||
\o Follow the \l{Patterns and practices} that we use in Qt Creator.
|
||
\o Take advantage of Qt. Don't re-invent the wheel. Think about what parts
|
||
of your code are generic enough that they might be incorporated into
|
||
Qt proper.
|
||
\o Document interfaces. Right now we use qdoc, but changing to doxygen
|
||
is being considered.
|
||
\endlist
|
||
|
||
|
||
\section1 Submitting Code
|
||
|
||
See http://qt.gitorious.org/qt/pages/QtContributionGuidelines
|
||
|
||
\section1 Code Constructs
|
||
|
||
We have several guidelines on code constructs, some of these exist to
|
||
make the code faster, others to make the code clearer. Yet others
|
||
exist to allow us to take advantage of the strong type checking in C++.
|
||
|
||
\list 1
|
||
\o Declaration of variables should wait as long as possible. The rule
|
||
is: "Don't declare it until you need it." In C++ there are a lot of
|
||
user defined types, and these can very often be expensive to
|
||
initialize. This rule connects to the next rule too.
|
||
|
||
\o Make the scope of a variable as small as possible.
|
||
|
||
\o Prefer preincrement to postincrement whenever possible.
|
||
Preincrement has potential of being faster than postincrement. Just
|
||
think about the obvious implementations of pre/post-increment. This
|
||
rule applies to decrement too.
|
||
|
||
\code
|
||
++T;
|
||
--U;
|
||
-NOT-
|
||
T++; // not used in Qt Creator
|
||
U--; // not used in Qt Creator
|
||
\endcode
|
||
|
||
\o Try to minimize evaluation of the same code over and over. This is
|
||
aimed especially at loops.
|
||
|
||
\code
|
||
|
||
Container::iterator end = large.end();
|
||
for (Container::iterator it = large.begin(); it != end; ++it) {
|
||
...;
|
||
}
|
||
-NOT-
|
||
for (Container::iterator it = large.begin();
|
||
it != large.end(); ++it) {
|
||
...;
|
||
}
|
||
\endcode
|
||
|
||
|
||
\o Using Qt's foreach is ok in non-time critical code when using a QTL
|
||
container. It is a nice way to keep line noise down and to give the
|
||
loop variable a proper name:
|
||
|
||
\code
|
||
foreach (QWidget *widget, container)
|
||
doSomething(widget);
|
||
|
||
-VS-
|
||
|
||
Container::iterator end = container.end();
|
||
for (Container::iterator it = container.begin(); it != end; ++it)
|
||
doSomething(*it);
|
||
\endcode
|
||
|
||
If the loop variable can be made const, do so. This can prevent
|
||
unnecessary detaching of shared data in some cases. So:
|
||
|
||
\code
|
||
foreach (const QString &name, someListOfNames)
|
||
doSomething(name);
|
||
|
||
- NOT -
|
||
|
||
foreach (QString name, someListOfNames)
|
||
doSomething(name);
|
||
\endcode
|
||
|
||
|
||
\section1 Formatting
|
||
|
||
\section2 Naming rules
|
||
|
||
\list
|
||
\o Class names are capitalized, and function names lowercased.
|
||
\o Variables and functions start with a lower case letter.
|
||
\o Enums are named like Classes, values are in loweri case, containing
|
||
some part of the name of the enum type.
|
||
\endlist
|
||
|
||
|
||
\section2 Declaration of variables
|
||
|
||
\list
|
||
\o Each consecutive word in a variable's name starts with a capital letter.
|
||
|
||
\o Avoid short (e.g., a, rbarr, nughdeget) names whenever possible.
|
||
Single character variable names are only okay for counters and
|
||
temporaries, where the purpose of the variable is obvious.
|
||
|
||
\o Declare each variable on a separate line.
|
||
\code
|
||
QString a = "Joe";
|
||
QString b = "Foo";
|
||
-NOT-
|
||
QString a = "Joe", b = "Foo"; // not used in Qt Creator
|
||
\endcode
|
||
[Note that 'QString a = "Joe"' is formally calling a copy constructor
|
||
on a temporary constructed from a string literal and therefore has the
|
||
potential of being more expensive then 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, Qt Creator code favours the '=' idiom as
|
||
it is in
|
||
line with the traditional C-style initialization, _and_ cannot be
|
||
mistaken as function declaration, _and_ reduces the level of nested
|
||
parantheses in more initializations.]
|
||
|
||
\o Avoid abbreviations
|
||
|
||
// Wrong
|
||
int a, b;
|
||
char *c, *d;
|
||
|
||
// Correct
|
||
int height;
|
||
int width;
|
||
char *nameOfThis;
|
||
char *nameOfThat;
|
||
|
||
\o Wait with declaring a variable until it is needed. This is especially
|
||
important when initialization is done at the same time.
|
||
\endlist
|
||
|
||
|
||
|
||
\section2 Pointers and references
|
||
|
||
\code
|
||
char *p = "flop";
|
||
char &c = *p;
|
||
-NOT-
|
||
char* p = "flop"; // not used in Qt Creator
|
||
char & c = *p; // not used in Qt Creator
|
||
\endcode
|
||
|
||
Also note that we will have:
|
||
\code
|
||
const char *p;
|
||
-NOT-
|
||
char const * p; // not used in Qt Creator
|
||
\endcode
|
||
|
||
|
||
Using a plain 0 for Null pointer constants is always correct and
|
||
least effort to type. So:
|
||
\code
|
||
void *p = 0;
|
||
-NOT-
|
||
void *p = NULL; // not used in Qt Creator
|
||
-NOT-
|
||
void *p = '\0'; // not used in Qt Creator
|
||
-NOT-
|
||
void *p = 42 - 7 * 6; // also not used in Qt Creator
|
||
\endcode
|
||
Note: As an exception, imported third party code as well as code
|
||
interfacing the "native" APIs (src/support/os_*) can use NULL.
|
||
|
||
|
||
\section2 Operator names and parentheses
|
||
\code
|
||
operator==(type)
|
||
-NOT-
|
||
operator == (type) // not used in Qt Creator
|
||
\endcode
|
||
|
||
The == is part of the function name, separating it makes the
|
||
declaration look like an expression.
|
||
|
||
|
||
\section2 Function names and parentheses
|
||
\code
|
||
void mangle()
|
||
-NOT-
|
||
void mangle () // not used in Qt Creator
|
||
\endcode
|
||
|
||
|
||
|
||
\section2 Indentation
|
||
Four spaces, no tabs.
|
||
|
||
|
||
|
||
\section2 Whitespace
|
||
\list
|
||
\o Use blank lines to group statements together where suited.
|
||
\o Always use only one blank line.
|
||
\o Always use a single space after a keyword, and before a curly brace.
|
||
\endlist
|
||
|
||
\code
|
||
// Wrong
|
||
if(foo){
|
||
}
|
||
|
||
// Correct
|
||
if (foo) {
|
||
}
|
||
\endcode
|
||
|
||
For pointers or references, always use a single space before '*' or '&',
|
||
but never after.
|
||
Avoid C-style casts when possible.
|
||
\code
|
||
// Wrong
|
||
char* blockOfMemory = (char* ) malloc(data.size());
|
||
|
||
// Correct
|
||
char *blockOfMemory = (char *)malloc(data.size());
|
||
char *blockOfMemory = reinterpret_cast<char *>(malloc(data.size()));
|
||
\endcode
|
||
Of course, in this particulare case, using \c new might be an even better
|
||
option.
|
||
|
||
Braces
|
||
As a base rule, the left curly brace goes on the same line as the
|
||
start of the statement:
|
||
\code
|
||
// Wrong
|
||
if (codec)
|
||
{
|
||
}
|
||
|
||
// Correct
|
||
if (codec) {
|
||
}
|
||
\endcode
|
||
|
||
Exception: Function implementations and class declarations always have
|
||
the left brace on the start of a line:
|
||
\code
|
||
static void foo(int g)
|
||
{
|
||
qDebug("foo: %i", g);
|
||
}
|
||
|
||
class Moo
|
||
{
|
||
};
|
||
\endcode
|
||
|
||
Use curly braces when the body of a conditional statement contains more
|
||
than one line, and also if a single line statement is somewhat complex.
|
||
\code
|
||
// Wrong
|
||
if (address.isEmpty()) {
|
||
return false;
|
||
}
|
||
|
||
for (int i = 0; i < 10; ++i) {
|
||
qDebug("%i", i);
|
||
}
|
||
|
||
// Correct
|
||
if (address.isEmpty())
|
||
return false;
|
||
|
||
for (int i = 0; i < 10; ++i)
|
||
qDebug("%i", i);
|
||
\endcode
|
||
|
||
Exception 1: Use braces also if the parent statement covers several
|
||
lines / wraps
|
||
\code
|
||
// Correct
|
||
if (address.isEmpty()
|
||
|| !isValid()
|
||
|| !codec)
|
||
return false;
|
||
\endcode
|
||
|
||
Note: This could be re-written as:
|
||
|
||
\code
|
||
// Als correct
|
||
if (address.isEmpty())
|
||
return false;
|
||
|
||
if (!isValid())
|
||
return false;
|
||
|
||
if (!codec)
|
||
return false;
|
||
\endcode
|
||
|
||
Exception 2: Use braces also in if-then-else blocks where either the
|
||
if-code or the else-code covers several lines
|
||
\code
|
||
// Wrong
|
||
if (address.isEmpty())
|
||
--it;
|
||
else {
|
||
qDebug("%s", qPrintable(address));
|
||
++it;
|
||
}
|
||
|
||
// Correct
|
||
if (address.isEmpty()) {
|
||
--it;
|
||
} else {
|
||
qDebug("%s", qPrintable(address));
|
||
++it;
|
||
}
|
||
|
||
// Wrong
|
||
if (a)
|
||
if (b)
|
||
...
|
||
else
|
||
...
|
||
|
||
// Correct
|
||
if (a) {
|
||
if (b)
|
||
...
|
||
else
|
||
...
|
||
}
|
||
\endcode
|
||
|
||
Use curly braces when the body of a conditional statement is empty
|
||
\code
|
||
// Wrong
|
||
while (a);
|
||
|
||
// Correct
|
||
while (a) {}
|
||
\endcode
|
||
|
||
|
||
\section2 Parentheses
|
||
Use parentheses to group expressions:
|
||
\code
|
||
// Wrong
|
||
if (a && b || c)
|
||
|
||
// Correct
|
||
if ((a && b) || c)
|
||
|
||
// Wrong
|
||
a + b & c
|
||
|
||
// Correct
|
||
(a + b) & c
|
||
\endcode
|
||
|
||
|
||
\section2 Line breaks
|
||
Keep lines shorter than 100 characters; insert line breaks if necessary.
|
||
Commas go at the end of a broken line; operators start at the beginning
|
||
of the new line. The operator is at the end of the line to avoid having
|
||
to scroll if your editor is too narrow.
|
||
\code
|
||
// Wrong
|
||
if (longExpression +
|
||
otherLongExpression +
|
||
otherOtherLongExpression) {
|
||
}
|
||
|
||
// Correct
|
||
if (longExpression
|
||
+ otherLongExpression
|
||
+ otherOtherLongExpression) {
|
||
}
|
||
\endcode
|
||
|
||
|
||
\section2 Declarations
|
||
|
||
- Use this order for the access sections of your class: public,
|
||
protected, 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). [Obviously not true since this is
|
||
for developers, and we do not want one developer only to be able to
|
||
read and understand the implementation of class internals. Lgb]
|
||
|
||
- Avoid declaring global objects in the declaration file of the class.
|
||
If the same variable is used for all objects, use a static member.
|
||
|
||
- Avoid global or static variables.
|
||
|
||
|
||
\section2 API/ABI stability
|
||
We currently do not gurantee any API nor ABI compatibility between releases.
|
||
|
||
|
||
\section2 File headers
|
||
|
||
If you create a new file, the top of the file should include a
|
||
header comment equal to the one found in other source files of Qt Creator.
|
||
|
||
\section2 Include order
|
||
|
||
Always go from less general to more general. In a typical implementation
|
||
file that would look like
|
||
\code
|
||
#include "myownheader.h"
|
||
...
|
||
#include "other_headers_from_my_own_plugin.h"
|
||
...
|
||
#include <other_plugin/headers_from_other_plugin.h>
|
||
...
|
||
#include <QtCore/QSomeCoreClass>
|
||
...
|
||
#include <QtGui/QSomeGuiClass>
|
||
...
|
||
#include <some_system_C++_header>
|
||
...
|
||
#include <some_system_C_header>
|
||
\endcode
|
||
This order ensures that the headers are self-contained.
|
||
|
||
Using <...> instead of "..." for headers from other plugins helps
|
||
spotting plugin-external dependencies in the sources.
|
||
|
||
Using empty lines between blocks of "peer" headers are encouraged.
|
||
|
||
\section2 Documentation
|
||
|
||
The documentation is generated from source and header files.
|
||
You document for the other developers, not for yourself.
|
||
In the header you should document interfaces, i.e. what the function does,
|
||
not the implementation.
|
||
In the .cpp files you document the implementation if the implementation
|
||
in non-obvious.
|
||
|
||
\section1 Patterns and practices
|
||
|
||
\section2 Passing file names
|
||
|
||
Qt Creator API expects file names in "portable" format, i.e. with '/'
|
||
instead of '\\' even on Windows. If you want to pass a file name to
|
||
the API that comes from the user, you need to convert it with
|
||
QDir::fromNativeSeparators first. Whenever you present a file name to the user,
|
||
you need to convert it back to native format with QDir::toNativeSeparators.
|
||
|
||
When comparing file names consider using FileManager::fixFileName which
|
||
makes sure that paths are clean and absolute and also takes Windows'
|
||
case-insensitivity into account (but is an expensive operation).
|
||
|
||
\section2 Plugin extension points
|
||
|
||
A plugin extension point is an interface that is provided by a plugin
|
||
to be implemented by others. The plugin then retrieves all
|
||
implementations of the interface and uses them, they "extend" the
|
||
functionality of the plugin. A common pattern is that the
|
||
implementations of the interface are put into the global object pool
|
||
during plugin initialization, and the plugin retrieves them from the
|
||
object pool at the end of plugin initialization.
|
||
|
||
For example: The Find plugin provides the FindFilter interface for
|
||
others to implement. With the FindFilter interface, additional search
|
||
scopes can be added, that appear in the Advanced Search dialog. The
|
||
Find plugin retrieves all FindFilter implementations (from the global
|
||
object pool, see below) and presents them in the dialog, forwarding the
|
||
actual search request to the correct FindFilter implementation, which
|
||
then performs the search.
|
||
|
||
\section2 Using the global object pool
|
||
|
||
You can add objects to the global object pool via
|
||
\l{ExtensionSystem::PluginManager::addObject()}, and retrieve objects
|
||
of a specific type again via
|
||
\l{ExtensionSystem::PluginManager::getObjects()}. This should mostly
|
||
be used for implementations of \l{Plugin extension points}.
|
||
|
||
Cases where you should not use it are:
|
||
\list
|
||
\o Singletons. Don't put a singleton into the pool, and don't retrieve
|
||
it from there. Use the singleton pattern instead.
|
||
\endlist
|
||
|
||
|
||
\section2 C++ features
|
||
|
||
\list
|
||
\o Don’t use exceptions _unless you know what you do_.
|
||
\o Don’t use RTTI (Run-Time Type Information; that is, the typeinfo
|
||
struct, the dynamic_cast or the typeid operators, including throwing
|
||
exceptions) _unless you know what you do_.
|
||
\o Use templates wisely, not just because you can.
|
||
|
||
Hint: Use the compile autotest to see whether a C++ feature is supported
|
||
by all compilers in the test farm.
|
||
|
||
\o All code is ascii only (7-bit characters only, run man ascii if unsure)
|
||
\list
|
||
\o Rationale: We have too many locales inhouse and an unhealthy
|
||
mix of UTF-8 and latin1 systems. Usually, characters > 127 can
|
||
be broken without you even knowing by clicking SAVE in your
|
||
favourite editor.
|
||
\o For strings: Use \nnn (where nnn is the octal representation
|
||
of whatever locale you want your string in) or \xnn (where nn
|
||
is hexadecimal).
|
||
Example: QString s = QString::fromUtf8("\213\005");
|
||
\o For umlauts in documentation, or other non-ASCII characters,
|
||
either use qdoc’s \unicode command or use the relevant macro;
|
||
e.g. \uuml for ü
|
||
\endlist
|
||
|
||
\o Avoid the use of anonymous namespaces in favor of the static keyword
|
||
if possible. A name localized to the compilation unit with static is
|
||
guaranteed to have internal linkage. For names declared in anonymous
|
||
namespaces the C++ standard unfortunately mandates external linkage.
|
||
(7.1.1/6, or see various discussions about this on the gcc mailing
|
||
lists)
|
||
|
||
\endlist
|
||
|
||
|
||
\section2 QObject usage
|
||
|
||
\list
|
||
|
||
\o Every QObject subclass must have a Q_OBJECT macro, even if it
|
||
doesn’t have signals or slots, if it is intended to be used
|
||
with qobject_cast<>.
|
||
|
||
\o Normalize the arguments for signals + slots
|
||
(see QMetaObject::normalizedSignature) inside connect statements
|
||
to safe a few cycles faster signal/slot lookups.
|
||
You can use $QTDIR/util/normalize to normalize existing code.
|
||
|
||
\endlist
|
||
|
||
|
||
\section2 Including headers
|
||
|
||
\list
|
||
\o Prefer use this form to include Qt headers:
|
||
\c{#include <QtCore/QWhatEver>}.
|
||
\o Order includes from most-specific to least-specific, i.e.
|
||
\list
|
||
\o \c{#include "myclass.h"}
|
||
\o \c{#include "otherclassinplugin.h"}
|
||
\o \c{#include <otherplugin/someclass.h>"}
|
||
\o \c{#include <QtModule/QtClass>"}
|
||
\o \c{#include <stdthing>"}
|
||
\o \c{#include <system.h>"}
|
||
\endif
|
||
Add empty line between long blocks and try to keep
|
||
alphabetical order within a block.
|
||
\endlist
|
||
|
||
\section2 Casting
|
||
|
||
\list
|
||
\o Avoid C casts, prefer C++ casts (static_cast, const_cast,
|
||
reinterpret_cast) Rationale: Both reinterpret_cast and
|
||
C-style casts are dangerous, but at least reinterpret_cast
|
||
won’t remove the const modifier.
|
||
\o Don’t use dynamic_cast, use qobject_cast for QObjects or
|
||
refactor your design, for example by introducing a type()
|
||
method (see QListWidgetItem) _unless you know what you do_.
|
||
\endlist
|
||
|
||
|
||
\section Compiler/Platform specific issues
|
||
|
||
\list
|
||
\o Be extremely careful when using the question mark operator.
|
||
If the returned types aren’t identical, some compilers generate
|
||
code that crashes at runtime (you won’t even get a compiler warning).
|
||
\code
|
||
QString s;
|
||
// crash at runtime - QString vs. const char *
|
||
return condition ? s : "nothing";
|
||
\endcode
|
||
|
||
\o Be extremely careful about alignment.
|
||
|
||
Whenever a pointer is cast such that the required alignment of
|
||
the target is increased, the resulting code might crash at runtime
|
||
on some architectures. For example, if a const char * is cast to an
|
||
const int *, it’ll crash on machines where integers have to be
|
||
aligned at a two- 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.
|
||
\code
|
||
union AlignHelper
|
||
{
|
||
char c;
|
||
int i;
|
||
};
|
||
\endcode
|
||
|
||
\o Anything that has a constructor or needs to run code to be
|
||
initialized cannot be used as global object in library code,
|
||
since it is undefined when that constructor/code will be run
|
||
(on first usage, on library load, before main() or not at all).
|
||
|
||
Even if the execution time of the initializer is defined for
|
||
shared libraries, you’ll get into trouble when moving that code
|
||
in a plugin or if the library is compiled statically:
|
||
|
||
\code
|
||
// global scope
|
||
// Wrong - default constructor needs to be run to initialize x:
|
||
static const QString x;
|
||
|
||
// Wrong - constructor that takes a const char * has to be run :
|
||
static const QString y = "Hello";
|
||
|
||
// Super wrong:
|
||
QString z;
|
||
|
||
// Wrong, call time of foo() undefined, might not be called at all:
|
||
static const int i = foo();
|
||
\endcode
|
||
|
||
Things you can do:
|
||
|
||
\code
|
||
// global scope
|
||
// Works - no constructor must be run, x set at compile time:
|
||
static const char x[] = "someText";
|
||
|
||
// Works - y will be set at compile time:
|
||
static int y = 7;
|
||
|
||
// Works - will be initialized statically, no code being run.
|
||
static MyStruct s = {1, 2, 3};
|
||
|
||
// Pointers to objects are ok, no code needed to be run to
|
||
// initialize 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");
|
||
}
|
||
\endcode
|
||
|
||
Note: Static objects in function scope are no problem, the constructor
|
||
will be run the first time the function is
|
||
entered. The code is not reentrant, though.
|
||
|
||
|
||
\o A char is signed or unsigned dependent on the architecture. Use signed
|
||
char or uchar if you explicitely want a signed/unsigned char.
|
||
The following code will break on PPC, for example:
|
||
|
||
\code
|
||
char c = 'A';
|
||
// WRONG - condition is always true on platforms where the
|
||
// default is unsigned:
|
||
if (c < 0) { ... }
|
||
\endcode
|
||
|
||
\o Try to avoid 64-bit enum values. The aapcs embedded ABI hard codes
|
||
all enum values to a 32-bit integer.
|
||
\endlist
|
||
|
||
|
||
\section2 Aestethics
|
||
|
||
\list
|
||
|
||
\o Prefer enums to define constants over static const int or defines.
|
||
enum values will be replaced by the compiler at compile time,
|
||
resulting in faster code defines are not namespace safe (and look ugly).
|
||
\o Prefer verbose argument names in headers.
|
||
Qt Creator will show the argument names in their completion-box.
|
||
It will look better in the documentation.
|
||
|
||
\endlist
|
||
|
||
|
||
\section2 Things to avoid
|
||
|
||
\list
|
||
\o Do not inherit from template/tool classes _unless you know what
|
||
you do_. Possible pitfalls: The destructors are not virtual,
|
||
leading to potential memory leaks. The symbols are not exported
|
||
(and mostly inline), leading to interesting symbol clashes.
|
||
Example: Library A has class Q_EXPORT X: public QList<QVariant> {};
|
||
and library B has class Q_EXPORT Y: public QList<QVariant> {};.
|
||
Suddenly, QList’s symbols are exported from two libraries – /clash/.
|
||
\o Don’t mix const and non-const iterators. This will silently crash
|
||
on broken compilers.
|
||
|
||
\code
|
||
// Wrong:
|
||
for (Container::const_iterator it = c.begin(); it != c.end(); ++it)
|
||
// Correct:
|
||
for (Container::const_iterator it = c.constBegin(); it != c.constEnd(); ++it)
|
||
\endcode
|
||
\endlist
|
||
|
||
\section2 Binary and Source Compatibility:
|
||
|
||
\list
|
||
\o Definitions:
|
||
\list
|
||
\o Qt 4.0.0 is a major release, Qt 4.1.0 is a minor release,
|
||
Qt 4.1.1 is a patch release.
|
||
\o Backward binary compatibility: Code linked to an earlier
|
||
version of the library keeps working.
|
||
\o Forward binary compatibility: Code linked to a newer
|
||
version of the library works with an older library.
|
||
\o Source code compatibility: Code compiles without modification.
|
||
\endlist
|
||
|
||
\o TRY TO keep backward binary compatibility and backward source code
|
||
compatibility in minor releases.
|
||
NOTE: This is not yet mandatory.
|
||
|
||
\o TRY TO Keep backward and forward binary compatibility and forward
|
||
and backward source code compatibility in patch releases
|
||
\list
|
||
\o Don’t add/remove any public API (e.g. global functions,x
|
||
public/protected/private methods)
|
||
\o Don’t reimplement methods (not even inlines,
|
||
nor protected/private methods)
|
||
\o Check BinaryCompatibilityWorkarounds for ways to keep b/c
|
||
\endlist
|
||
NOTE: This is not yet mandatory!
|
||
|
||
\o Some information on binary compatibility:
|
||
http://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C++
|
||
|
||
\endlist
|
||
|
||
|
||
\section2 Namespacing
|
||
|
||
Read QtInNamespace and keep in mind that all of Qt Creator is
|
||
“namespace aware” code.
|
||
|
||
|
||
\section2 Conventions for public header files
|
||
|
||
Our public header files have to survive the strict settings of
|
||
some of our users. All installed headers have to follow these rules:
|
||
|
||
\list
|
||
|
||
\o No C style casts (-Wold-style-cast). Use static_cast, const_cast
|
||
or reinterpret_cast, for basic types, use the constructor form:
|
||
int(a) instead of (int)a. See chapter “Casting” for more info.
|
||
|
||
\o No float comparisons (-Wfloat-equal). Use qFuzzyCompare to compare
|
||
values with a delta. Use qIsNull to check whether a float is
|
||
binary 0, instead of comparing it to 0.0, or, prefered, move
|
||
such code into an implementaion fole.
|
||
|
||
\o Don’t hide virtual methods in subclasses (-Woverloaded-virtual).
|
||
If the baseclass A has a virtual int val() and subclass B an
|
||
overload with the same name, int val(int x), A’s val function
|
||
is hidden. Use the using keyword to make it visible again, and
|
||
add the following silly workaround for broken compilers:
|
||
\code
|
||
class B: public A
|
||
{
|
||
#ifdef Q_NO_USING_KEYWORD
|
||
inline int val() { return A::val(); }
|
||
#else
|
||
using A::val;
|
||
#endif
|
||
};
|
||
\code
|
||
|
||
\o Don’t shadow variables (-Wshadow). Avoid things like this->x = x;
|
||
|
||
\o Don’t give variables the same name as functions declared in
|
||
yours class.
|
||
|
||
\o Always check whether a preprocessor variable is defined before
|
||
probing its value (-Wundef).
|
||
|
||
\code
|
||
// Wrong:
|
||
#if Foo == 0
|
||
|
||
// Correct:
|
||
#if defined(Foo) && Foo == 0
|
||
|
||
// Wrong. We don't want to do "clever" things like that.
|
||
// Use the one above instead, for better readability.
|
||
#if Foo - 0 == 0
|
||
|
||
\endcode
|
||
|
||
\endlist
|
||
|
||
*/
|