Header file

Include guards prevent double declaration errors and speed up the compilation.
#ifndef HEADERFILENAME_H
#define HEADERFILENAME_H
  /* contents of headerfilename.h here ... */
#endif

In C++, C library header file is always the C name prefixed with the letter c in which the .h file suffix has been dropped, for example <cassert> and <cstdlib>. To use the C++ named C library need explicitly make it visible with using directive using namespace std;


If the source code is in C++ but not C, to prevent C/ C++ compiler compile it in C way, add compilation guard as below:
#ifndef __cplusplus
  #error Must use C++ for this application.
#endif

The name __STDC__ is defined when compiling Standard C. Of course, __cplusplus and __STDC__ are never defined at the same time.


Write declaration to call external functions written in C in header file which can be used for C and C++ and coping with C++ name mangling feature (to support type-safe linking and name overloading).
#ifdef __cplusplus
extern "C" {
#endif
  /* all C declarations come here ... */
#ifdef __cplusplus
}
#endif
This linkage directive shows the function is written in a different programming language. Use extern "C" linkage directive to make C function available to C++ program and vice versa.
// single statement linkage directive
extern "C" void exit(int);
// compound statement linkage directive
extern "C" {
  #include <cmath> // all are C functions
  int printf(const char* ...);
  int scanf(const char* ...);
}

extern "C" double calc(double dparm) // can be called from C programs
Naturally, this works only for non-member functions. If want to call member functions (include virtual functions) from C, need to provide a simple wrapper. If want to call overloaded functions from C, must provide wrappers with distinct names for the C code to use.
// C++ code:
class C {
  // ...
  virtual double f(char);
};

extern "C" double call_C_f(C* p, int i)	// wrapper function
{
  return p->f(i);
}

void f(int);
void f(double);

extern "C" void f_i(int i) { f(i); }
extern "C" void f_d(double d) { f(d); }

/* C code: */
double call_C_f(struct C* p, int i);
void f_i(int);
void f_d(double);

void ccc(struct C* p, int i)
{
  double d = call_C_f(p,i);
  f_i(i);
  f_d(d);
  /* ... */
}

These techniques can be used to call a C++ library from C code even if cannot (or do not want to) modify the C++ headers.


The folder seperator character of Windows and Unix/ Linux is different. To conceal the platform difference,
#ifdef WIN32  //  in Windows environment
  #include "Include\HeaderFileName.h"
#else //  in Unix/ Linux environment
  #include "Include/HeaderFileName.h"
#endif

Predefined names:
  1. __LINE__ - current line number of the file being compiled.
  2. __FILE__ - name of the current file being compiled.
  3. __TIME__ - compilation time of the file currently being compiled in hh:mm:ss
  4. __DATE__ - compilation date of the file currently being compiled in mmm dd yyyy
if ( element_count == 0 )
  cerr << "Error: " << __FILE__ << " : line " << __LINE__
       << "element_count must be non-zero.\n";

defined identifier is useful when need to have #if, #elif, #endif as there are only #ifdef or #ifndef available, no something like "#elifdef".


Some care should be taken in designing header files. The declarations provided should logically belong together. A header file takes time to compile. If it is too large or filled with too many disparate elements, programmers may be reluctant to incur the compile-time cost of including it.

Header file should never contain a definition for a non-inline function or an object. The inclusion of any of these definitions in two or more files of the same program will result in a linker error complaining about multiple definitions.
// Error
extern int ival = 10; // non-inline because explicit initialization
double fica_rate;
extern void dummy() {}
const char* msg = "?? oops: error: ";

// OK, inline
typedef unsigned char uchar;
const uchar INLINE = 128;
inline bool is_relational( uchar tok ) { /* ... */ }
const char *const msg = "?? oops: error: ";

Precompiled headers can sometimes help; but sometimes they can make the problem worse, too. Turning on precompiled headers may result in large dumps which take longer to read in than the headers they replace. The lesson to be learned is to keep headers as small as possible. When developing a library, provide many small headers which must be included separately, rather than one header which includes the whole library.

<iostream> is known to take relatively long to compile because they are made up of several other internal headers and template code. To speed up, replace it with the lightweight header <iosfwd> in the header files, but still require <iostream> in the implementation files.


C++ doesn't do a very good job of separating interfaces from implementations. In particular, class definitions include not only the interface specification, but also a fair number of implementation details.
#include <string>
#include "date.h"
#include "address.h"
#include "country.h"

class Person {
public:
  Person(const string& name, const Date& birthday,
         const Address& addr, const Country& country);
  string GetName() const { return name_; }

protected: // implementation detail
  string name_;
  Date birthDate_;
  Address address_;
  Country citizenship_;
};

Unfortunately, this sets up a compilation dependency between the file defining Person and these include files. As a result, if any of these auxiliary classes changes its implementation, or if any of the classes on which it depends changes its implementation, the file containing the Person class must be recompiled, as must any files that use the Person class.

The reason C++ need implementation details of a class in the class definition is to know the size of the class. To decouple them, define the implementation detail as seperate struct/ class and the original class store only a pointer or reference to the implementation class, similar to the solution of Brittle base class problem. Disadvantages

So use these techniques during development to minimize the impact on user when implementations change. Replace them with concrete classes for production use when it can be shown that the difference in speed and/ or size is significant enough to justify the increased coupling between classes.

There are three immediate implications to reduce compilation dependency:
  1. Avoid using objects when object references and pointers will do. Define references and pointers to a type with only a declaration for the type; defining objects of a type necessitates the presence of the type's definition.
  2. Use class declarations instead of class definitions whenever possible. Note that never need a class definition to declare a function using that class, even if the function passes or returns the class type by value. Only when it is called, its definition must be visible.
  3. Don't #include header files unless it won't compile without them. Instead, manually declare the classes needed and let user#include the additional headers necessary to make their code compile. This is why <iosfwd> is introduced.
Index