C++ – Programming Style in Large Scale Applications

ccoding-style

Recently I've been browsing source code of large applications written in C++ to learn a bit but I couldn't help but notice that most if not all use a lot of IFDEFs and class-less functions (where they could have been class members/methods).

An example is Qt Creator IDE source code:

http://qt.gitorious.org/qt-creator/qt-creator/blobs/master/src/app/main.cpp

If you notice, it has a bunch of functions around the main() function; one of them, for example, is:

static inline void toHtml(QString &t)

the above method is defined outside while I think it could have been part of some utility class maybe.

Also, I think IFDEFs make the programs messy (again my opinion).

My question is: is it just an accepted practice in C++ world to mix procedural and OO code like that?

Best Answer

It is a rather subjective question - there are many schools of practice for writing C++ code.

C++ affords you the ability to pick and choose what paradigms you want to use for writing your code. The language allows you to use procedural, object-oriented, generic, and functional constructs (especially with C++11 features).

You don't necessarily need to build utility classes (unlike, say, in Java, where everything has to be in a class), as static functions in a class may not be required and can just be standalone free functions.

Conditional compilation is a necessity because of disparate platforms. I worked in defense, and have written code using Qt, boost, libraries for video games, and have worked on a variety of platforms including Linux, HP-UX, AIX, Windows, IRIX, and Mac OSX - platforms are different enough that code written for one does not necessarily work on a different platform. Some easy examples are:

  • Endianess - Some architectures (like x86) are little endian, but many other architectures (like SPARC) are big endian. Networking is also reliant on big endian addressing. When you write code across different architectures, sometimes you need to conditionally compile in code that supports such endian differences.

  • Different library calls - Windows uses winsock as its networking API, and it's similar to BSD Sockets used by Unix and Unix-derivatives. However, it is different enough that the function calls aren't similar. Additionally, there are library calls that exist in some flavors of Unix that don't exist in other flavors, or derivatives, so conditional compilation is needed for that too.

  • Compiler differences or versioning differences - Different versions of compilers, or different compilers altogether, may support functionality/libraries that aren't supported by other compilers.

Even if you use a library like Qt, which aims to be cross-platform, there is still conditional compilation happening, as you found out. These cross-platform libraries are there to reduce your own needs to do conditional compilation.


Additionally, coding styles and standards may be influencing how code is written.

Just more anecdotes from my past - C++ can be written in many ways as influenced by internal standards. For example, some organizations restrict the use of the C++ Standard Library, especially in regards to using the standard containers (like std::vector and std::list) - this may be due to the environment involved (like embedded systems).


Ultimately, it does come down to this: there are many ways to write C++, and it is acceptable to mix and match different paradigms in a single C++ program and code base, because there may be better/simpler ways to express something in one paradigm than to be locked into using a single pattern for an entire code base.

If you want to look at large C++ code bases that have high code quality, I will say that Boost and Qt are among the better examples.

Generally and widely accepted conventions and idioms for C++ programming are provided in books like Effective C++ and More Effective C++