<LI><A HREF="#no_stl">Don't use STL</A></LI>
<LI><A HREF="#no_fordecl">Don't declare variables inside <TT>for()</TT></A></LI>
<LI><A HREF="#no_nestedclasses">Don't use nested classes</A></LI>
+ </OL>
+ <BR>
+ <LI>Other compiler limitations</LI>
+ <OL>
<LI><A HREF="#no_ternarywithobjects">Use ternary operator ?: carefully</A></LI>
+ <LI><A HREF="#no_autoaggregate">Don't use initializers with automatic arrays</A></LI>
+ <LI><A HREF="#no_dtorswithoutctor">Always have at least one constructor in a class with destructor</A></LI>
</OL>
<BR>
<LI>General recommendations</LI>
<OL>
+ <LI><A HREF="#no_cppcommentsinc">No C++ comments in C code></A></LI>
<LI><A HREF="#no_globals">No global variables with constructor</A></LI>
<LI><A HREF="#no_warnings">Turn on all warnings and eradicate them</A></LI>
<LI><A HREF="#no_assume_sizeof">Don't rely on <TT>sizeof(int) == 2</TT>...</A></LI>
<LI><A HREF="#no_assignment_in_if">No assignments in conditional expressions</A></LI>
- <LI><A HREF="#no_comment_code">Use <TT>#if 0</TT> rather than comments to temporarily
- disable blocks of code</A></LI>
+ <LI><A HREF="#no_comment_code">Use <TT>#if 0</TT> rather than comments to temporarily disable blocks of code</A></LI>
+ <LI><A HREF="#no_overloaded_virtuals">Avoid overloaded virtual functions</A></LI>
<LI><A HREF="#no_extra_semicolon">Don't use extra semi-colons on top level</A></LI>
</OL>
<BR>
<LI><A HREF="#no_carriagereturn">Avoid carriage returns in cross-platform code</A></LI>
<LI><A HREF="#no_caps_in_filenames">Use only lower letter filenames</A></LI>
<LI><A HREF="#no_incomplete_files">Terminate the files with a new-line</A></LI>
+ <LI><A HREF="#no_case_only_diff">Avoid globals differing by case only</A></LI>
</OL>
<BR>
<LI>Style choices</LI>
<OL>
<LI><A HREF="#naming_conv">Naming conventions: use <TT>m_</TT> for members</A></LI>
- <LI><A HREF="#no_void_param">Don't use <TT>void</TT> for functions without
- arguments</A></LI>
- <LI><A HREF="#no_const_int">Don't use <TT>const</TT> for non pointer/reference
- arguments</A></LI>
+ <LI><A HREF="#no_void_param">Don't use <TT>void</TT> for functions without arguments</A></LI>
+ <LI><A HREF="#no_const_int">Don't use <TT>const</TT> for non pointer/reference arguments</A></LI>
</OL>
</UL>
<LI>More about naming conventions</LI>
<OL>
<LI><A HREF="#wx_prefix">Use wx or WX prefix for all public symbols</A></LI>
- <LI><A HREF="#wxdllexport">Use WXDLLEXPORT with all classes/functions in
- wxMSW/common code</A></LI>
+ <LI><A HREF="#wxdllexport">Use WXDLLEXPORT with all classes/functions in wxMSW/common code</A></LI>
<LI><A HREF="#set_get">Use Set/Get prefixes for accessors</A></LI>
<LI><A HREF="#constants">wxNAMING_CONSTANTS</A></LI>
</OL>
<P>A nice side effect is that you don't need to recompile all the files
including the header if you change the PrivateLibClass declaration (it's
an example of a more general interface/implementation separation idea).
+</OL>
+ <BR>
+ <LI>Other compiler limitations</B></LI><P>
+This section lists the less obvious limitations of the current C++ compilers
+which are less restrictive than the ones mentioned in the previous section but
+are may be even more dangerous as a program which compiles perfectly well on
+some platform and seems to use only standard C++ featurs may still fail to
+compile on another platform and/or with another compiler.
+
+<OL>
<P><LI><A NAME="no_ternarywithobjects"></A><B>Use ternary operator ?: carefully</B></LI><P>
The ternary operator <TT>?:</TT> shouldn't be used with objects (i.e. if any
of its operands are objects) because some compilers (notable Borland C++) fail
else
s = s2;
</PRE>
+
+ <P><LI><A NAME="no_autoaggregate"></A><B>Don't use initializers with automatic arrays</B></LI><P>
+The initializers for automatic array variables are not supported by some older
+compilers. For example, the following line
+<PRE>
+ int daysInMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+</PRE>
+will fail to compile with HP-UX C++ compiler.
+<P><U>Workaround</U>: either make the array static or initialize each item
+separately: in the (stupid) example above, the array should be definitely
+declared as <TT>static const</TT> (assuming that the leap years are dealt with
+elsewhere somehow...) which is ok. When an array is really not const, you
+should initialize each element separately.
+
+ <P><LI><A NAME="no_dtorswithoutctor"></A><B>Always have at least one constructor in a class with destructor</B></LI><P>
+It is a good rule to follow in general, but some compilers (HP-UX) enforce it.
+So even if you are sure that the default constructor for your class is ok but
+it has a destructor, remember to add an empty default constructor to it.
</OL>
<BR>
also contains some C/C++ specific remarks in the end which are less
important.
<OL>
+ <P><LI><A NAME="no_cppcommentsinc"><B>No C++ comments in C code></B></LI><P>
+Never use C++ comments in C code - not all C compilers/preprocessors
+understand them. Although we're mainly concerned with C++ here, there are
+several files in wxWindows sources tree which are compiled with C compiler.
+Among them are <TT>include/wx/setup.h</TT> and <TT>include/wx/expr.h</TT>.
+
+Another thing related to C vs C++ preprocessor differences is that some old C
+preprocessors require that all directives start in the first column (while
+it's generally allowed to have any amount of whitespace before them in C++),
+so you should start them in the beginning of the line in files which are
+compiled with C compiler.
+
<P><LI><A NAME="no_globals"></A><B>No global variables with constructors</B></LI><P>
In C++, the constructors of global variables are called before the
<TT>main()</TT> function (or <TT>WinMain()</TT> or any other program entry point)
The reason is simple: if there are any <TT>/* ... */</TT> comments inside
<TT>...</TT> the second version will, of course, miserably fail.
+ <P><LI><A NAME="no_overloaded_virtuals"></A><B>Avoid overloaded virtual functions</B></LI><P>
+
+You should avoid having overloaded virtual methods in a base class because if
+any of them is overriden in a derived class, then all others must be overriden
+as well or it would be impossible to call them on an object of derived class.
+
+For example, the following code:
+
+<PRE>
+ 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"); // compile error here!
+</PRE>
+
+will fail to compile because the base class function taking <TT>filename</TT>
+is hidden by the virtual function overriden in the derived class (this is
+known as [virtual] function name hiding problem in C++).
+
+<P>
+The standard solution to this problem in wxWindows (where we have such
+situations quite often) is to make both <TT>Read()</TT> functions not virtual
+and introduce a single virtual function <TT>DoRead()</TT>. 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!).
+<P>
+So, the above declarations should be written as:
+<PRE>
+ 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) { ... }
+ };
+</PRE>
+
+This technique is widely used in many of wxWindows classes - for example,
+<TT>wxWindow</TT> has more than a dozen of <TT>DoXXX()</TT> functions which
+allows to have many overloaded versions of commonly used methods such as
+<TT>SetSize()</TT>
+
<P><LI><A NAME="no_extra_semicolon"></A><B>Don't use extra semi-colons on top level</B></LI><P>
Some compilers don't pay any attention to extra semicolons on top level, as in
<PRE>
like files without terminating new-line. Such files also give a warning message
when loaded to vim (the Unix programmer's editor of choice :-)), so please think
about terminating the last line.
+
+ <P><LI><A NAME="no_case_only_diff"></A><B>Avoid globals differing by case only</B></LI><P>
+The linker on VMS is case-insensitive. Therefore all external variables and
+functions which differ only in case are not recognized by the linker as
+different, so all externals should differ in more than the case only:
+i.e. <TT>GetId</TT> is the same as <TT>GetID</TT>.
+
</OL>
<BR>
setup as well to allow including <TT><wx/foo.h></TT> on any platform.<P>
Note that wxWindows implementation files should use quotes when including wxWindows
-headers, not angled brackets. Applications should use angled brackets. There
-is a reason for it (can anyone remember what this is?).
+headers, not angled brackets. Applications should use angled brackets. This
+ensures that the dependencies are correctly handled by the compiler.
<P><LI><A NAME="include_guards"></LI><B>Include guards</B><P>
To minimize the compile time C++ programmers often use so called include
The reason for the strange syntax for data is that some compilers use different
keyword ordering for exporting data.
-<P>There also several other places where you should take care of shared
-library case: all IMPLEMENT_xxx macros which are usually used in the
-corresponding .cpp files must be taken inside
-"<TT>#if !USE_SHARED_LIBRARY</TT>" and in the <TT>#if USE_SHARED_LIBRARY</TT>
-case you should put them inside <TT>common/cmndata.cpp</TT> file.
-
<P><LI><A NAME="set_get"></LI><B>Use Set/Get prefixes for accessors</B><P>
There is a convention in wxWindows to prefix the accessors (i.e. any simple, in
general, inline function which does nothing else except changing or returning