Coding Guidelines
This guide is intended for people who are (or intending to start) writing code for inclusion into the wxWidgets library. The guidelines here do not need to be followed when writing applications using wxWidgets as they typically don’t have to deal with all the platforms that the library itself supports, notably there is usually absolutely no reason to avoid the use of exceptions or the standard library in the application code.
Please notice that these guidelines apply for wxWidgets version 3.3 and newer; older versions still do not allow using Modern C++ (i.e., C++11 and newer) nor using any standard container (e.g., vector) or smart pointer (e.g., unique_ptr) classes.
Also notice that some parts of the existing code may not follow these guidelines, because it could have been written before the guidelines were put in place. However this is not a reason to not follow them for any new code. In other words, in case of a conflict between this document and the existing code, this document should be considered authoritative.
- Physical Files Organization
- Naming Conventions
- Coding Style
- Indent your code with 4 spaces (no tabs!)
- Use 80 character lines
- Put opening curly bracket on its own line
- Use spaces with keywords
- Order of parts in a class declarations
- Use
//
for most comments - Don’t use
void
for functions without arguments - Don’t use
const
for non pointer/reference arguments - Use
nullptr
rather than0
- Use
override
for overridden virtual methods - Use
wxFALLTHROUGH
inswitch
statements
- Restrictions on C++ Features
- Code Quality
- Message and Documentation Conventions
- Use well-formed language for messages
- Always start a sentence with a capital letter
- Always end a sentence with a period or other appropriate punctuation
- Never use “…” unless absolutely necessary
- Avoid “!” wherever possible
- Use only one space after a period and before a new sentence
- Don’t use unnecessary parentheses
Physical Files Organization
Use .cpp for C++ source file extension
Use .cpp
extension for the C++ files and .h
for the headers.
File locations
All headers are found under the directory include/wx
, both the public and
private ones. All source file are under the directory src
.
Both of these directories contain port-specific subdirectories, such as
include/wx/msw
or src/gtk
. If a class has only a single implementation for
all platforms, it is declared in a single include/wx/foo.h
header and
implemented in a single src/common/foo.cpp
file, i.e. src/common
subdirectory should be used for platform-independent code when there is no
platform-specific version.
A more common case is to have several different versions of the class for
different platforms. In this case, the header include/wx/foo.h
is still the
only header which can be directly included but it may and typically does
include platform-specific include/wx/port/foo.h
headers internally (where
port
is one of msw
, gtk
, osx
, …). The corresponding implementation
files are src/port/foo.cpp
and the common, not platform-specific, part, if
any, is in src/common/foocmn.cpp
.
Additionally, a GUI class can have a “generic” implementation, that is one
written in wxWidgets itself instead of using the platform-specific API. Such
implementation is declared in include/wx/generic/foo.h
file (which is still
never included directly, but only from include/wx/foo.h
) and defined in
src/generic/foog.cpp
(notice the extra “g” at the end, to avoid confusion
with the native implementation called foo.cpp
). In some cases, you may
notice that a class has only the generic implementation, which seems to
contradict this explanation, but actually just means that we plan to add one
or more native implementations in the future – and this just hasn’t happened
yet.
Sometimes it can be useful to have a private header, i.e. one used only in the
implementation of wxWidgets but not by the outside code using the library.
Such files should be placed under include/wx/private
or
include/wx/port/private
for port-specific ones.
Reference API documentation is in the files under interface/wx
directory.
The rest of the manual is found under docs/doxygen
.
Standard file header
All wxWidgets files should start with the following standard header:
/////////////////////////////////////////////////////////////////////////////
// Name: src/common/foo.cpp
// Purpose: Implementation of wxFoo
// Author: Your Name <your@email.address>
// Created: 2019-02-07
// Copyright: (c) 2019 wxWidgets development team
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
Notice that the date should be in ISO format (YYYY-MM-DD). The licence must always be specified as wxWindows licence (not “wxWidgets licence”) while the copyright depends on the actual person or organization having contributed the code.
Include guards
Any header include/wx/foo/bar.h
must wrap its contents (i.e. everything
after the standard header comment) in an include guard:
#ifndef _WX_FOO_BAR_H_
#define _WX_FOO_BAR_H_
// ... all header contents ...
#endif // _WX_FOO_BAR_H_
Formally _WX
prefix makes this prefix a reserved word, however this style is
used in wxWidgets since 20+ years and hasn’t created any problems so far, so
we are going to continue using it.
Precompiled headers
A source file should always start by including the precompiled header file
wx/wxprec.h
which includes most of the commonly used wxWidgets headers if
precompiled headers support is used. If it isn’t, the individual headers
actually used by the code need to be included inside WX_PRECOMP
test. And
headers not included by wx/wxprec.h
need to be included in any case.
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
#include "wx/msgdlg.h" // This header is normally included from wx/wx.h
#endif
#include "wx/richmsgdlg.h" // But this one never is
Use WXDLLIMPEXP_XXX with all public classes and functions
All public types and data must be declared with WXDLLIMPEXP_XXX
in their
declaration to be usable outside of the wxWidgets DLL. XXX
here can be one
of BASE
, CORE
and so on depending on the library the symbol is
exported from, see include/wx/dlimpexp.h
for the full list. For example:
bool WXDLLIMPEXP_BASE wxSomeUtilityFunction();
class WXDLLIMPEXP_CORE wxSomeGUIClass { ... };
WXDLLIMPEXP_DATA_CORE(extern wxApp*) wxTheApp;
Use only lower case filenames
To avoid conflicts between case-sensitive and case-insensitive (even if case-preserving) file systems, only use lower case ASCII letters (and numbers if necessary) in the file names.
Naming Conventions
The guidelines in this section describe the conventions used for naming identifiers in wxWidgets code, please follow them to avoid surprising people reading it.
Here is a quick example summarizing all the conventions described below:
extern void wxGlobalFunction();
enum wxFileOpenMode
{
wxFILEOPEN_READ,
wxFILEOPEN_WRITE,
wxFILEOPEN_READWRITE
};
void wxCountXs()
{
static int s_x;
#ifdef wxSOMETHING_OR_OTHER
s_x++;
#endif
}
class wxSomeClass
{
public:
int GetSomeX() const { return m_someX; }
void SetSomeX(int x) { m_someX = x; }
private:
int m_someX;
};
Use wx prefix for all public symbols
The prefix wx
must be used for all public classes, functions, constants
and macros, no exceptions.
Some old macros and a very few extremely old functions don’t have this prefix, but all new public identifiers should use it. Of course, class members don’t need to follow this rule as they don’t have global visibility.
Use CamelCaseFunctions and camelCaseVariables
Use CamelCase
for types (classes, structs, enums, unions), methods and
functions and camelCase
for the variables.
Use UPPER_CASE for constants
Use UPPER_CASE
for constants, whether they are enum elements or preprocessor
macros (the latter should be avoided if possible).
The same convention is also used for the macros, after taking the wx
prefix
into account.
Use m_
prefix for member variables
All member variables should have m_
prefix to distinguish them from local
variables.
Possible exception: simple structs, not having any methods (except, possibly the constructor), may not use this prefix (rationale: there is no ambiguity as to what kind of variable this is if it’s always used via struct object, pointer or reference).
Static variables should have s_
prefix to allow to easily grep for them.
Member static variables combine both rules above and use ms_
prefix
(rationale for choosing this over sm_
: grepping for s_
to check for
possible multi-threading problems finds them with this naming convention).
Global variables shouldn’t normally be used at all, but if they are, should
have g_
prefix.
Exception: public global variables follow the rule above and so use wx
prefix instead of g_
one. They also typically use The
as part of their
name, e.g. wxTheApp
or wxTheClipboard
.
Use Set/Get prefixes for accessors
There is a convention in wxWidgets to prefix the accessors (i.e. any simple, in
general, inline function which does nothing else except changing or returning
the value of a member variable) with either Set
or Get
.
On the contrary, do not use Get
prefix for a function which is
non-trivial, i.e. does something else than simply returning the internally
stored value.
Coding Style
As any style, the guidelines here are at least partly subjective (although some of them do have an objective rationale), but please follow them even if they contradict your personal preferences to ensure consistent appearance of all the code in the library.
Indent your code with 4 spaces (no tabs!)
Configure your editor to use spaces, not TABs, for indentation and use 4 spaces per indentation level.
If you use Emacs, you can put the following in your .emacs file to help get indentation right:
;; CC-mode setup
(defun my-c-mode-common-hook ()
;; my customizations for all of c-mode, c++-mode, and objc-mode
(c-set-offset 'substatement-open 0)
(c-set-offset 'case-label 1)
(c-set-offset 'defun-block-intro 4)
(c-set-offset 'access-label -2)
(setq c-recognize-knr-p nil)
(setq c-basic-offset 4)
(setq-default indent-tabs-mode nil)
;; Set the return key to autoindent
(local-set-key "\C-m" 'reindent-then-newline-and-indent)
)
(add-hook 'c-mode-common-hook 'my-c-mode-common-hook)
Mattia Barbon suggests this:
(setq-default indent-tabs-mode nil)
(setq c-default-style
'( ( c++-mode . "stroustrup" )
( c-mode . "stroustrup" ) )
)
Robin Dunn has this alternative:
(defun my-c-mode-common-hook ()
""
(interactive)
(c-set-style "bsd")
;;
;; configure vars for cc-mode based items
;;
(setq c-auto-newline nil
c-tab-always-indent nil
c-basic-offset 4
c-comment-only-line-offset 0
c-hanging-comment-ender-p nil
c-hanging-comment-starter-p nil
c-comment-continuation-stars "** "
c-cleanup-list (list 'empty-defun-braces
'defun-close-semi
'list-close-comma
'scope-operator
)
compilation-ask-about-save nil
compilation-read-command t
compilation-scroll-output t
fill-column 78
comment-column 40
tab-width 8
indent-tabs-mode nil
)
(c-toggle-auto-hungry-state -1)
(local-set-key "\C-m" 'newline-and-indent)
(local-set-key "\C-cc" 'comment-region)
(setq c-electric-pound-behavior '(alignleft))
)
(add-hook 'c-mode-common-hook 'my-c-mode-common-hook)
If you use vi(m), you can add the following line to your ~/.vimrc or ~/.exrc:
au BufReadPost */wxWidgets/*/*.cpp,*/wxWidgets/*/*.h set sw=4 ts=4 et cin
(et
and cin
don’t exist in plain vi)
Use 80 character lines
Please keep the line length under 80 characters.
Rationale: even with modern wide screen monitors, it is difficult to review side by side diffs for lines longer than that. Too long lines also often indicate some problem in the code, such as excessive nesting (in this case you should simplify the logic or refactor the function by extracting the inner parts in separate functions) or too complex expressions (in this case, simplify them by using named variables for the intermediate results).
Put opening curly bracket on its own line
Don’t leave {
on the preceding line, always put it on its own line, e.g.
if ( condition )
{
if-statements;
}
else
{
else-statements;
}
Use spaces with keywords
Use a space after a keyword such as if
, for
, while
or switch
and
around the expression used by this keyword. Do not use spaces in these
positions for the function calls but still use them to separate function
arguments. For example:
for ( init; condition; loop )
{
switch ( expression )
{
case 0:
CallSomeFunction(with, some, arguments);
break;
}
}
Order of parts in a class declarations
By convention, please put the public parts of the class first, then protected, then private. The idea is to be able to quickly see the public API of a class without having to read through uninteresting implementation details in the public sections.
Also, please put all wxWidgets macros which must be used in the class
declaration (such as wxDECLARE_EVENT_TABLE
) at the end as, again, these are
implementation details and shouldn’t get in the way of the person who is
reading the file.
Use //
for most comments
Use C++ style //
comments for most of them, not only single line ones.
Reserve C style /* ... */
comments only for high level, very long
explanatory comments. When using C style comments do not use any
intermediate asterisks to make the comments easier to reformat.
Please always put a space after the beginning of a C++ comment, e.g. use //
Whatever
instead of //Whatever
.
Notice that wxWidgets does not use Doxygen style comments (/** ... */
or
///
) in its sources, these comments are only used in the special interface
headers from which the API documentation is generated.
Don’t use void
for functions without arguments
In ANSI C, void Foo()
takes an arbitrary number of arbitrarily typed
arguments (although the form void Foo(...)
is preferred) and void Foo(void)
doesn’t take any arguments. In C++, however, the situation is different and
both declarations are completely equivalent. As there is no need to write
void
in this situation, let’s not write it – it can only be confusing and
create an impression that it really means something when it’s not at all the
case.
Don’t use const
for non pointer/reference arguments
In both C and C++ an argument passed by value cannot be modified – or, more
precisely, if it is modified in the called function, only the local copy is
really changed, not the caller’s variable. So, semantically speaking, there is
no difference between void Foo(int)
and void Foo(const int)
. However, the
const
keyword is confusing here, adds nothing to the code and even cannot be
removed if Foo()
is virtual and overridden (because the names are mangled
differently). So, for arguments passed by value you shouldn’t use const
.
Of course, it doesn’t apply to functions such as
void PrintMessage(const char* text)
where const
is mandatory.
Use nullptr
rather than 0
Always use nullptr
in the expressions involving the pointers instead of
just the constant 0
.
A related advice is to use '\0'
instead of 0
in the expressions involving
char
types.
Use override
for overridden virtual methods
When overriding a virtual method of the base class, use override
in its
declaration like this:
class Base
{
public:
virtual void DoSomething();
};
class Derived : public Base
{
public:
void DoSomething() override;
};
Notice that the virtual
keyword is redundant as override
already
identifies the method as being virtual, so it can be omitted, even in most of
the existing code both keywords are used together as override
is a
relatively recent addition and was just added to the existing method
declarations.
Use wxFALLTHROUGH
in switch
statements
Use the special wxFALLTHROUGH
macro in case of intentional fall through to
the next case
clause in a switch
statement:
bool vertical = false,
positive = true;
switch ( keycode )
{
case WXK_UP:
vertical = true;
wxFALLTHROUGH;
case WXK_LEFT:
positive = false;
break;
...
}
The use of this macro allows to enable warnings given by newer compilers about unintentional fall through, which is a common bug.
Restrictions on C++ features
Don’t use C++14 or newer
Unfortunately, wxWidgets has to support ancient GCC versions, so the only Modern C++ allowed is what C++11 offers.
Don’t use exceptions
wxWidgets doesn’t use exceptions, mostly for backwards compatibility reasons: the existing code doesn’t expect wxWidgets functions to throw exceptions, as they had never been thrown before and so could be broken if they started now. It is also sometimes useful to compile the code without exceptions support, especially for embedded platforms where the resulting savings in the code size and speed can be noticeable.
In any case, as exceptions are not used for error reporting, the failure of
the functions in wxWidgets API must be indicated by a special return value,
e.g. false
for functions returning bool
or NULL
for the functions
returning pointers to objects. The special case of constructors, which have no
return value, is typically handled by providing an IsOk()
method indicating
whether the object was constructed successfully and, for all
wxWindow
-derived classes, also by providing a default constructor (which
never fails) and a function called, by convention, Create()
performing the
same initialization as is done by the non-default ctor, but returning a
boolean value indicating whether it succeeded or failed.
Don’t use RTTI
wxWidgets doesn’t use standard C++ RTTI, i.e. dynamic_cast<>
and typeid
shouldn’t be used in its code. This is done to allow compiling code which
disables RTTI support for performance reasons and also because wxWidgets has
its own wxRTTI mechanism for wxObject
-derived classes which is necessary
anyhow, as, unlike the standard C++ RTTI, it also allows creation of C++
objects by name.
So wxDynamicCast()
should be used instead of dynamic_cast<>
(assuming it
needs to be used at all) and wxObject::GetClassInfo()
instead of typeid
.
Notice that static_cast<>
, const_cast<>
and reinterpret_cast<>
can be
used as they don’t require any run-time support.
Don’t use alternative operator representations
C++ standard defines the following reserved words: or
, and
, not
, xor
,
bitand
, bitor
, compl
, and_eq
, or_eq
, not_eq
, or_eq
which can be used instead of the usual C operators &&
, ||
, ~
, etc.
Support for these operators varies among compilers and some of them don’t support them at all while others require special options to enable their use. For this reason, and also because there is absolutely no advantage in using these keywords compared to the traditional operators, as well as for the reasons of consistency, these keywords must not be used in wxWidgets sources.
Code Quality
The recommendations in this section are much less subjective and describe best practices when writing C++ code which should be followed in most, if not all, large scale C++ projects, and thus apply to wxWidgets.
Turn on all warnings and eradicate them
Give the compiler a chance to help you – turn on all warnings! You should always use the maximum available warning level of your compiler and understand and correct each of them. If, for whatever reasons, a compiler gives a warning on some perfectly legal line of code and you can’t change it, please insert a comment indicating it in the code. Most often, however, all compiler warnings may be avoided (not suppressed!) with minimal changes to your code.
Avoid C style casts
Prefer C++ static_cast<>
and const_cast<>
to the C style casts if they can
be used to replace them. Also use reinterpret_cast<>
(while trying to avoid
it as much as possible, of course), although C style casts are allowed for
some low level code with a lot of unavoidable casts where using
reinterpret_cast<>
can make it even less readable.
Notice that dynamic_cast<>
should not be used in wxWidgets code, see the
RTTI section.
No assignments in conditional expressions
Although close to the heart of many C programmers (I plead guilty), code like
classical if ( (c = getchar()) != EOF )
is bad because it prevents you
from enabling “assignment in conditional expression” warning (see also
above) which is helpful to detect common mistypes like
if ( x = 2 )
instead of if ( x == 2 )
.
Avoid default
in switches over enums
Include cases for all enum
elements and do not include the default
case in
switch
statements over the values of an enum type. This ensures that the
compiler will be able to warn if a newly added enum element is not handled by
the switch.
For example, replace this code:
bool ConfirmOverwrite(wxFile::OpenMode mode)
{
switch ( mode )
{
case wxFile::write:
case wxFile::write_append:
case wxFile::write_excl:
// Ask the user about overwriting the file.
break;
default:
return true;
}
return wxMessageBox("Overwrite?", ...) == wxID_YES;
}
with this, semantically equivalent, version:
bool ConfirmOverwrite(wxFile::OpenMode mode)
{
switch ( mode )
{
case wxFile::write:
case wxFile::write_append:
case wxFile::write_excl:
return wxMessageBox("Overwrite?", ...) == wxID_YES;
case wxFile::read:
case wxFile::read_write:
return true;
}
wxFAIL_MSG("Unreachable");
return true; // Still needed to pacify some compilers.
}
See debug macros section for more about the use of
wxFAIL_MSG()
.
Avoid overloaded virtual functions
Avoid having overloaded virtual methods in a base class because if any of them is overridden in a derived class, then all others must be overridden as well or it would be impossible to call them on an object of derived class. For example, take following code:
class Base
{
public:
virtual void Read(wxFile& file);
virtual void Read(const wxString& filename);
};
class Derived : public Base
{
public:
virtual void Read(wxFile& file) { ... }
};
// ...
Derived d;
d.Read("some_filename");
This will fail to compile because the base class function taking filename
is
hidden by the virtual function overridden in the derived class (this is known as
[virtual] function name hiding problem in C++).
The standard solution to this problem in wxWidgets (where we have such
situations quite often) is to make both Read()
functions not virtual and
introduce a single virtual function DoRead()
. Usually, it makes sense because
the function taking a filename is (again, usually) implemented in terms of the
function reading from a file anyhow (but making only this functions not virtual
won’t solve the above problem!).
So, the above declarations should be written as:
class Base
{
public:
void Read(wxFile& file);
void Read(const wxString& filename);
protected:
virtual void DoRead(wxFile& file);
};
class Derived : public Base
{
protected:
virtual void DoRead(wxFile& file) { ... }
};
This technique is widely used in many of wxWidgets classes – for example,
wxWindow
has more than a dozen of DoXXX()
functions which allows to have
many overloaded versions of commonly used methods such as SetSize()
.
Don’t use boolean function arguments
Using boolean parameters in the public function usually is a bad API design
idea for two reasons which are explained below using the example of wxWidgets
wxExecute
function used to launch an external process but which are,
in fact, quite general:
-
Readability:
When you see
wxExecute(TRUE)
orwxExecute(FALSE)
you have absolutely no idea what does it mean. Even if you know (from reading the documentation) that the parameter specifies whether the program execution should be synchronous or not, you still don’t know which one is which:TRUE
andFALSE
here are just the “bare numbers” which don’t help the person reading the code to understand what do they stand for. The solution is the same for the other bare numbers: replace them with the symbolic constants. Indeed, when you seewxExecute(wxEXEC_ASYNC)
you have no troubles understanding it on the first reading nor is there any danger of confusing the sync and async calls. -
Inextensible:
Suppose now that you want to add another parameter to
wxExecute()
, for example whether a new console window should be opened, you have to add another parameter. And if it is bool as well you end up with such clear and expressible pearls aswxExecute(TRUE, FALSE)
.The solution is simple: replace
bool
withint
and add some flags with symbolic names. This solves both problems at once: not only you can avoid adding a new parameter to the function (which is especially important if it already has two or three of them) but also a call such aswxExecute(wxEXEC_ASYNC | wxEXEC_NEW_CONSOLE)
is as readable as it gets.The only situations in which bool parameters may be used are those where their meaning is immediately clear from the function purpose, for example it is not unreasonable to have a
Show(bool show = TRUE)
function which either shows or hides something. But in vast majority of the cases, the meaning is not immediately clear to the reader and using the symbolic flag constants is a better alternative.
Use forward declarations whenever possible
It’s a really trivial piece of advice, but remember that using forward declarations instead of including the header of corresponding class is better because not only does it minimize the compile time, it also simplifies the dependencies between different source files.
On a related subject, in general, you should try not to include other headers from a header file.
Use debugging macros
wxWidgets provides the debugging macros wxASSERT, wxFAIL
and wxCHECK_RET
in
file. Please use them as often as you can – they will never do you any harm
but can greatly simplify the bug tracking both for you and for others.
Also, please use wxFAIL_MSG("not implemented")
instead of writing stubs for
not (yet) implemented functions which silently return incorrect values –
otherwise, a person using a not implemented function has no idea that it is, in
fact, not implemented.
As all debugging macros only are deactivated when NDEBUG
is defined, build
your code in debug version, i.e. without /DNDEBUG
, when testing to give them
a chance to help you.
Message and documentation conventions
These apply to messages in the wxWidgets source, as well as to wxWidgets documentation.
Use well-formed language for messages, not abbreviations or pseudo-English
Always start a sentence with a capital letter
Always end a sentence with a period or other appropriate punctuation
Never use “…” unless absolutely necessary
Avoid “!” wherever possible
It’s rarely necessary to emphasise a point this much (the same applies to documentation).
Use only one space after a period and before a new sentence
Don’t add a lone space after a period if it’s not going to be followed by another sentence.
Don’t use unnecessary parentheses in messages and documentation
Instead, rearrange the sentence.