Next Previous Table of Contents
Close to the end of this handbook, I want to summarize several issues that programmers should watch out while coding. These are mostly C++ programming tips that relate to KDE and Qt programming especially and are partly taken from the KDE Developer's Center which can be found on the Internet at http://www.kde.org, some have been added by my own experience.
First of all, when creating sourcefiles, you should always use lowercase filenames. KDevelop supports this guideline already if you stick to its filename aut-suggestion. This makes it easier for other developers to remember what source files to look for when they have to debug your application.
The classnaming for KDE projects is recommended to be:
KMyWidget
for an application specific widget.myWidgetPointer()
get
-prefix. You should prefer using a descriptive name for
those types of classmembers. Example: b_myboolean
is a private member. The method returning the current value would be e.g.
myBoolean()
.
Hardcoding any path should be avoided by using the KDE File System Standard. You only have to watch the installation path for your
files by the according macros of the Makefile.am
as described in this handbook. Within the code, you should use the methods of
KApplication
to retrieve the actual path.
Another thing already mentionend is class documentation. You should stick to use KDoc
formatting rules as they are used by all KDE
developers to document their classes. You should at least add a single line to all of your classmembers for yourself to remember the
prurpose and for others to reuse code. The code-reuse by the GPL makes much more sense if you know where to find an already existing
solution if classes are documented. The Qt library referece is a good example of well-documented interfaces, though it doesn't use
KDoc
.
new
to create widgetsWithin your implementation, you should always prefer to create widgets on the heap with new
. The Qt library has a nice habbit to
automatically delete all child widgets you created with new
, so you don't ever have to use delete
again in those cases. This
is one of the most important practical features of the Qt library and you should make wide use of this.
When it comes to debugging, you should make use of the macros KDebug
provides. Those are similar to the Qt macros, but can be
retrieved by the keycode STRG+ALT+F12. See the
KDE Library Reference Guide for
more information about the event filtering of these Macros. You could as well use assert()
, but should try to be consistent with
your debugging code.
const
-declarationsFurther, you should use const
declarations for member functions that should or do not change any private member. This would be the
case for all methods that only return the current value of a private member. This avoids changing the value accidently and will catch
those logical errors at compile time. Now, towards initializing const members you should stick to do that together with using
static
in the declaration and initialize the value outside the constructor like this:
class foo {
static const int value;
};
const foo::value = 10;
ANSI C++ allows to initialize the member inside the constructor but you should avoid this as a few compilers are not capable of this
feature.
As explained in section
User Interaction, you should stick to the access rights and the declaration
by virtual
when overwriting virtual methods. At least you shouldn't reduce the access of a virtual method from protected to
private.
Class-headers should be included where you dereference any object or instance of a class in your sourcecode. That means if your class uses a member of another class, replace the #include directive with a forward declaration of the class, e.g instead of:
#include <qpushbutton.h>
class KMyWidget:public QWidget
{
private:
QPushButton* ok_button;
};
you should prefer to only declaring the class QPushButton
in the header file:
class QPushButton;
class KMyWidget:public QWidget
{
private:
QPushButton* ok_button;
};
and place the include directive into the according sourcefile where e.g. the instance ok_button
is dereferenced with any method of
the class QPushButton
. This saves compile time at any rate, especially if you're using instances of classes that your're working
on. The compiler will recompile all souces that include the header file if you made any changes on the interface of the class,
therefore a simple addition of a method that only returns an internal value will lead to a recompilation of all sources tha include
the header file of the class.
Also you should leave out formal parameters of methods that don't necessarily require the actual parameter to work. This avoids the
unused parameter
warnings of your compiler when he sees a method that retrieves a formal parameter but doesn't use it in its
implementation. Usually, you will set some default arguments for several methods. Those should always be placed in the declaration of
the class member instead of setting them in the member implementation.
config.h
KDevelop projects as well as any other project that is using autoconf
to create a configure
-script produce a file
config.h
after executing the configure
-script on the target machine. The values found by configure
are listed there and
can be used within the sourcecode. The directive to include the config.h
file is:
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
One of the most recently used entries of config.h
is probably the type-definition of bool
for compilers that don't comply
with the newest ANSI C++ draft.
0
instead of NULL
You should stickt to using 0
directly instead of NULL
for preset values like the Qt and KDE libraries already do. This
increases portablility of your applications towards different compilers that have problems with NULL
.
You should declare temporary instances always before using them. This is generally considered better than direct use. Example:
// Don't:
for( int i=0; i<n; i++){
//do something
};
// Do:
int i;
for(i=0; i<n; i++){
//do something
};
This also counts on using temporaries in function calls:
// Don't:
setColor( &(QColor(black)) );
// Do:
QColor color(black);
setColor( &color );
As KDevelop projects use the GNU tools to create projects, it is ensured that your application will run on almost every Unix system. However, you may encounter problems when actually compiling your application under another Unix, because header files are located somewhere different or you need another implementation especially when it comes to using OS-specific low-level functions which can differ from system to system.
When programming with C++ and Qt/KDE you should also notice that the Qt collection classes have a rich set of functionality that is already compiler/OS independend and makes things much easier, starting with strings (QString) to file reading/writing (QFile); so using Qt will make using OS defines almost obsolete in most cases.
Anyway, when using Qt and you still have to use #defines for your application, you should include
qglobal.h
and make use of the already predefined defines for various Operating Systems and compilers
which preselects the below defines already.
Instead of letting the packagers of OS-Vendors applying any patches to your application (like most do where necessary e.g. for building rpmīs or packages/ports), you should use defines for those sections that are operating-system specific (but you donīt have to use -D for compiling, the Operating System defines are handled automatically). The following lists the available systems and their defines (additional defines in brackets):
#ifdef _AIX
#if defined(bsdi) || defined(__bsdi__)
#if defined (ultrix) || defined(__ultrix) || defined(__ultrix__)
#if defined(DGUX)
#ifdef __FreeBSD__
#if defined(__GNU__)
#if defined (hpux) || defined (__hpux) || defined (__hpux__)
#if defined(linux) || defined(__linux) || defined(__linux__)
#ifdef __NetBSD__
#ifdef __OpenBSD__
#if defined(__osf__)
#if defined(__QNX__)
#if defined(_UNIXWARE)
#if defined(sco) || defined(_UNIXWARE7)
#if defined(_SCO_DS) || defined(M_UNIX) || defined(M_XENIX)
#if defined(sgi) || defined(__sgi)
#if defined (sun) || defined (__sun) || defined (__sun__)
#if defined (_OS_SUN_) || defined (__SVR4)
Next Previous Table of Contents