Monday, December 28, 2009

Conditional inclusion of header files

Ram (one of my peers, name changed) complained that he was unable to create an object of class (say clsX).

We have the practise of having our class declarations in header files. So the declaration of the class clsX was in X.h file.

To define an object of class clsX in a soure file, Ram had included the header file X.h in the source file. Despite that he was unable to define the object of class clsX. He got compiler error for the same.

Ram complained Ravi (one of my peers, name changed) that he was unable to create an object of class clsX. Ravi is the one who wrote the class clsX.

Ravi worked on it to provide the following report:
  1. I am not sure about why this problem is occurring, but it seems to be because of some issue with C++ compilers, as mentioned in these two posts I found for the error C2143 -
    1. http://sabbour.wordpress.com/2006/12/30/error-c2143-syntax-error-missing-before/
    2. http://www-subatech.in2p3.fr/~photons/subatech/soft/carnac/CPP-INC-1.shtml
  2. I tried moving the class declaration to the source file, and then removed the header file inclusion. The problem was resolved, which means the contents of the header file 'clsX.h' do not have any syntax error.
  3. I removed the inclusion of the header file 'clsX.h' and instead used a forward declaration as follows, and this solution worked fine.
  4. Please use a forward declaration for the class clsTable, as mentioned in point 3 above, to continue your analysis. I shall look into the problem further to ascertain the root cause.
I decided to have a hand on the problem under discussion. By seeing the compiler error, I got that the declaration of the class clsX didn't reach the source file despite the inclusion of header file X.h.

We use preprocessor directives to conditionally include a header file content into other source file. This is to avoid the duplication of declarations.

On checking the macro that is used along with the preprocessor directives in X.h, I found that the macro used is already defined in some other header file (say Y.h). The header file Y.h is already included in the source file in which X.h is also included. Because of which the macro defined in Y.h eliminated the inclusion of X.h contents.

I.e.

Y.h
 #ifndef _Y_H
 #define _Y_H
 ...
 ...
 #endif

X.h
 #ifndef _Y_H
 #define _Y_H
 declaration of class clsX
 #endif

Z.c
 #include "../Y/Y.h"
 #include "../X/X.h"
 define object of class clsX

Here you can see that the contents of header file X.h (I.e. declaration of class clsX), won't be included. This is because the contents of header file X.h would be included in file Z.c only if the macro _Y_H is not defined before. But macro _Y_H is already defined in Z.c by the inclusion of header file Y.h.

I pointed out the mistake of using the same macro for two header files which solved the problem.