X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/97979ddfbe4bc199c6b0389e352d6963c17c64a0..ea51d98d659465219574b290015390b8783afe51:/docs/html/standard.htm diff --git a/docs/html/standard.htm b/docs/html/standard.htm index 196224130c..1b8e6cf15d 100644 --- a/docs/html/standard.htm +++ b/docs/html/standard.htm @@ -24,7 +24,7 @@ wxWindows Programmer Style Guide by Vadim Zeitlin

This guide is intended for people who are (or intending to start) writing code -for wxWindows class library. +for wxWindows class library.

The guide is separated into two parts: the first one addresses the general @@ -34,8 +34,8 @@ variety of platforms. The second part details the wxWindows code organization an its goal it to make wxWindows as uniform as possible without imposing too many restrictions on the programmer.

-Acknowledgements: This guide is partly based on +Acknowledgements: This guide is partly based on C++ portability guide by David Williams.

@@ -50,16 +50,18 @@ C++ portability guide by David Williams.

  • Don't use STL
  • Don't declare variables inside for()
  • Don't use nested classes
  • +
  • Use ternary operator ?: carefully

  • General recommendations
    1. +
    2. No C++ comments in C code>
    3. No global variables with constructor
    4. Turn on all warnings and eradicate them
    5. Don't rely on sizeof(int) == 2...
    6. No assignments in conditional expressions
    7. -
    8. Use #if 0 rather than comments to temporarily - disable blocks of code
    9. +
    10. Use #if 0 rather than comments to temporarily disable blocks of code
    11. +
    12. Avoid overloaded virtual functions
    13. Don't use extra semi-colons on top level

    @@ -70,15 +72,14 @@ C++ portability guide by David Williams.
  • Avoid carriage returns in cross-platform code
  • Use only lower letter filenames
  • Terminate the files with a new-line
  • +
  • Avoid globals differing by case only

  • Style choices
    1. Naming conventions: use m_ for members
    2. -
    3. Don't use void for functions without - arguments
    4. -
    5. Don't use const for non pointer/reference - arguments
    6. +
    7. Don't use void for functions without arguments
    8. +
    9. Don't use const for non pointer/reference arguments
    @@ -100,14 +101,14 @@ C++ portability guide by David Williams.
  • Indent your code with 4 spaces (no tabs!)
  • Order of parts in a class declarations
  • - +
  • More about naming conventions
    1. Use wx or WX prefix for all public symbols
    2. -
    3. Use WXDLLEXPORT with all classes/functions in - wxMSW/common code
    4. +
    5. Use WXDLLEXPORT with all classes/functions in wxMSW/common code
    6. Use Set/Get prefixes for accessors
    7. +
    8. wxNAMING_CONSTANTS

    @@ -123,7 +124,7 @@ C++ portability guide by David Williams.

    General C++ Rules

    - +

  • Don't use RTTI
  • RTTI stands for Run-Time Type Information and there is probably no other reason not to use it except the portability issue and the fact that it adds @@ -240,7 +241,7 @@ reason not to use it except the portability issue and the fact that it adds in the implementations I'm aware of).

    Workaround: use wxWindows RTTI system which allows you to do almost everything which the new C++ RTTI, except that, of course, you have to use -macros instead of the (horrible looking, BTW) dynamic_cast. +macros instead of the (horrible looking, BTW) dynamic_cast.

  • Don't use namespaces
  • This topic is subject to change with time, however for the moment all wxWindows @@ -312,17 +313,17 @@ you can try the following: private: class PrivateLibClass *m_pObject; }; - + // in the .cpp file class PrivateLibClass { ... }; - + PublicLibClass::PublicLibClass() { m_pObject = new PrivateLibClass; - + ... } - + PublicLibClass::~PublicLibClass() { delete m_pObject; @@ -331,20 +332,51 @@ you can try the following:

    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). + +

  • Use ternary operator ?: carefully
  • + The ternary operator ?: shouldn't be used with objects (i.e. if any +of its operands are objects) because some compilers (notable Borland C++) fail +to compile such code. +

    Workaround: use if/else instead. +

    +    wxString s1, s2;
    +
    +    // Borland C++ won't compile the line below
    +    wxString s = s1.Len() < s2.Len() ? s1 : s2;
    +
    +    // but any C++ compiler will compile this
    +    wxString s;
    +    if ( s1.Len() < s2.Len() )
    +        s = s1;
    +    else
    +        s = s2;
    +

  • General recommendations
  • While the recommendations in the previous section may not apply to you if you're only working with perfect compilers which implement the very newest directives of -C++ standard, this section contains compiler- (and language-) independent advice +C++ standard, this section contains compiler- (and language-) independent advice which must be followed if you wish to write correct, i.e. working, programs. It -also contains some C/C++ specific remarks in the end which are less +also contains some C/C++ specific remarks in the end which are less important.

      +

    1. No C++ comments in C code>
    2. +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 include/wx/setup.h and include/wx/expr.h. + +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. +

    3. No global variables with constructors
    4. In C++, the constructors of global variables are called before the -main() function (or WinMain() or any other program entry point) +main() function (or WinMain() or any other program entry point) starts executing. Thus, there is no possibility to initialize anything before the constructor call. The order of construction is largely implementation-defined, meaning that there is no guarantee that one global @@ -423,7 +455,7 @@ sizes are different. A small table illustrates it quite well: 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) warning which is helpful to detect common +above) which is helpful to detect common mistypes like if ( x = 2 ) instead of if ( x == 2 ).

    5. Use #if 0 rather than comments to temporarily @@ -443,6 +475,70 @@ instead of The reason is simple: if there are any /* ... */ comments inside ... the second version will, of course, miserably fail. +

    6. Avoid overloaded virtual functions
    7. + +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: + +

      +    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!
      +
      + +will fail to compile because the base class function taking filename +is hidden by the virtual function overriden in the derived class (this is +known as [virtual] function name hiding problem in C++). + +

      +The standard solution to this problem in wxWindows (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 wxWindows 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() +

    8. Don't use extra semi-colons on top level
    9. Some compilers don't pay any attention to extra semicolons on top level, as in

      @@ -494,11 +590,18 @@ While DOS/Windows compilers don't seem to mind, their Unix counterparts don't
       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.
      +
      +    

    10. Avoid globals differing by case only
    11. +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. GetId is the same as . +

    - +
  • Style choices
  • - All wxWindows specific style guidelines are specified in the next + All wxWindows specific style guidelines are specified in the next section, here are the choices which are not completely arbitrary, but have some deeper and not wxWindows-specific meaning. @@ -518,9 +621,9 @@ following code fragment is: void Foo::Bar(int x_) { ... - + x = x_; - + ... } @@ -591,7 +694,7 @@ 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 +

    Of course, it doesn't apply to functions such as void PrintMessage(const char *text) where const is mandatory. @@ -607,7 +710,7 @@ The wxWindows files for each supported platform have their own subdirectories in "include" and "src". So, for example, there is "src/msw", "include/gtk" etc. There are also two special subdirectories called "common" and "generic". The common subdirectory contains the files which are platform -independent (wxObject, wxString, ...) and the generic one the generic +independent (wxObject, wxString, ...) and the generic one the generic implementations of GUI widgets, i.e. those which use only other wxWindows classes to implement them. For the platforms where the given functionality cannot be implemented natively, the generic implementation is used and the native @@ -712,12 +815,12 @@ usage 'public domain' (the copyright holder does not assert the copyright).

  • Indent your code with 4 spaces (no tabs!)

  • Order of parts in a class declarations

    - +

  • More about naming conventions
    1. Use wx or WX prefix for all public symbols. wx should be used for functions and classes, WX for macros. -

    2. Use WXDLLEXPORT with all classes/functions in +

    3. Use WXDLLEXPORT with all classes/functions in wxMSW/common code The title says it all - every public (in the sense that it is not internal to the library) function or class should have WXDLLEXPORT macro in its @@ -732,16 +835,29 @@ WXDLLEXPORT_DATA(extern wxApp*) wxTheApp; The reason for the strange syntax for data is that some compilers use different keyword ordering for exporting data. -

      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 -"#if !USE_SHARED_LIBRARY" and in the #if USE_SHARED_LIBRARY -case you should put them inside common/cmndata.cpp file. -

    4. Use Set/Get prefixes for accessors

      -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 +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 the value of a member variable) with either Set or Get. + +

    5. wxNAMING_CONSTANTS

      +The constants in wxWindows code should be defined using enum C++ +keyword (and not with #define or static const int). They +should be declared in the global scope (and not inside class declaration) and +their names should start with a wx prefix. Finally, the constants +should be in all capital letters (except the first 2) to make it easier to +distinguish them from the variables with underscores separating the words. + +

      For example, file-related constants should be declared like this: +

      +enum
      +{
      +    wxFILEOPEN_READ,
      +    wxFILEOPEN_WRITE,
      +    wxFILEOPEN_READWRITE
      +};
      +
      +

  • Miscellaneous
  • @@ -751,7 +867,7 @@ It's really a trivial piece of advice, but remember that using forward declarati 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 +

    On a related subject, in general, you should try not to include other headers from a header file.

  • Use debugging macros

    @@ -764,7 +880,7 @@ 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 do something useful if the symbol -__DEBUG__ is defined, you should compile your programs in debug mode to profit +__WXDEBUG__ is defined, you should compile your programs in debug mode to profit from them.