Policies/Library Code Policy

This document describes some of the recommended conventions that should be applied in the KDE libraries (not applications). Respecting these guidelines helps create a consistant API and also may help ease maintainence of the libraries later. While these conventions are not mandatory, they are important guidelines, and should be respected unless you have a good reason to disregard them.
As an introduction, you should read the document Designing Qt-Style C++ APIs.

Naming Conventions

Class names starts with a capital K. The rest is in camel case. Function names starts with a lower case, but the first letter of each successive word is capitalized.

Unless dealing with central libraries (kdecore, kdeui), classes should be in the library namespace. In that case, it is the namespace which starts with K and the classes inside may not start with it. New libraries should choose their namespace.

The prefix 'set' is used for setters, but the prefix 'get' is not used for accessors. Accessors are simply named with the name of the property they access. The exception is for accessors of a boolean which may start with the prefix 'is'.

Notice that the member d is const to avoid modifying it by mistake. The private class must not be a nested class or it will be exported too if you added the _EXPORT keyword to the parent class.

If you are implementing an implicitly shared class, you should consider using QSharedData and QSharedDataPointer for d. If you don't use them, then use QAtomic for reference counting. Don't try to implement your own refcounting with integers.

Sometimes, complex code may be moved to a member method of the Private class itself. Doing this may give the compiler an extra register to optimize the code, since you won't be using "d" all the time.

Inline Code

Installed headers should compile with the following preprocessor defines: QT_NO_CAST_FROM_ASCII, QT_NO_CAST_TO_ASCII, QT_NO_KEYWORD. So don't forget QLatin1String.

No C casts in the header. Use static_cast if types are known. Use qobject_cast instead of dynamic_cast if types are QObject based. dynamic_cast is not only slower, but is also unreliable across shared libraries.

The solution is to use QFlags. If the options only apply to one function, call the enum FunctionNameOption and the QFlags typedef FunctionNameOptions. Do that even if there is only one option, this will allow you to add more options later and keep the binary compatibility.

Const References

Each object parameter that is not a basic type (int, float, bool, enum, or pointers) should be passed by constant reference. This is faster, because it is not required to do a copy of the object. Do that even for object that are already implicitly shared, like QString:

QString myMethod(const QString& foo, const QPixmap& bar, int number);

Signals and Slots

In the libraries, use Q_SIGNALS and Q_SLOTS instead of signals and slots. They are syntactically equivalent and should be used to avoid conflicts with boost signals, and with python's use of "slots" in its headers.

Properites

Consider using Q_PROPERTY for properties. The reason is that properties (especially thoses marked SCRIPTABLE) will be accessible through the javascript interface.

If you follow the propname / setPropname naming sheme, moc sets a special flag for the QMetaProperty.

Explicit Constructors

For each constructor, check if you should make the constructor explicit in order to minimize wrong use of the constructor.

Basically, each constructor that may take only one argument should be marked explicit unless the whole point of the constructor is to allow implicit casting.

Avoid including other headers in headers

Try to reduce as much as possible the number of includes in header files. This will generally help reduce the compilation time, especially for developers when just one header has been modified. It may also avoid errors that can be caused by conflicts between headers.

If an object in the class is only used by pointer or by reference, it is not required to include the header for that object. Instead, just add a forward declaration before the class.

In this example, the class KFoo uses KBar by reference, so we do not need to include KBar's header: