473,395 Members | 1,568 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

An idea for the recursive inclusion problem

Multiple inclusion of the same header file can cause the compilation
to fail because of multiple definitions of the same type. That's why
it's standard practice to write all headers like this:

// SomeClass.hh
#ifndef SOME_CLASS_HH
#define SOME_CLASS_HH

class SomeClass
{
...
};

#endif

In complex projects recursive inclusion happens. It can be a rather
long chain of headers including other headers in a loop, and it may
be easy to miss.
The problem is that when this happens, the compiler errors are
usually very confusing. In the worst case (this has happened to me)
the compiler starts giving errors on places which have so far
compiled without problems and you haven't touched for weeks. It can
easily be really confusing why the compiler suddenly started to
complain about something you haven't even modified. Unless you have
experienced it before, it can be really hard to guess that the
problem is in a recursive inclusion which formed when you wrote
that one #include in a seemingly unrelated header. (Depending on
the compiler and the project settings it may be completely unexpected
what will "break" first because of that.)

I was thinking: In most cases when this problem has happened to me,
it was easy to fix by removing the #include and replacing it with a
pre-declaration of the class, as this usually has happened only when
I use references/pointers to that class instead of instances. Thus if
all headers were written like this:

// SomeClass.hh
class SomeClass;

#ifndef SOME_CLASS_HH
#define SOME_CLASS_HH

class SomeClass
{
...
};

#endif

then recursive inclusion would not be a problem. If you are only
using pointer/references, then everything will compile and work ok.
And even if you are using the class as a member variable and you
simply can't do that, you will most probably get a more meaningful
error message, like "error: field `x' has incomplete type" (now you
only have to understand that "incomplete type" refers to the type
having only been pre-declared).

Can anyone think of a drawback of doing this?
Jul 5 '07 #1
6 3884
On Jul 5, 1:30 pm, Juha Nieminen <nos...@thanks.invalidwrote:
Multiple inclusion of the same header file can cause the compilation
to fail because of multiple definitions of the same type. That's why
it's standard practice to write all headers like this:

// SomeClass.hh
#ifndef SOME_CLASS_HH
#define SOME_CLASS_HH

class SomeClass
{
...

};

#endif

In complex projects recursive inclusion happens. It can be a rather
long chain of headers including other headers in a loop, and it may
be easy to miss.
The problem is that when this happens, the compiler errors are
usually very confusing. In the worst case (this has happened to me)
the compiler starts giving errors on places which have so far
compiled without problems and you haven't touched for weeks. It can
easily be really confusing why the compiler suddenly started to
complain about something you haven't even modified. Unless you have
experienced it before, it can be really hard to guess that the
problem is in a recursive inclusion which formed when you wrote
that one #include in a seemingly unrelated header. (Depending on
the compiler and the project settings it may be completely unexpected
what will "break" first because of that.)

I was thinking: In most cases when this problem has happened to me,
it was easy to fix by removing the #include and replacing it with a
pre-declaration of the class, as this usually has happened only when
I use references/pointers to that class instead of instances. Thus if
all headers were written like this:

// SomeClass.hh
class SomeClass;

#ifndef SOME_CLASS_HH
#define SOME_CLASS_HH

class SomeClass
{
...

};

#endif

then recursive inclusion would not be a problem. If you are only
using pointer/references, then everything will compile and work ok.
And even if you are using the class as a member variable and you
simply can't do that, you will most probably get a more meaningful
error message, like "error: field `x' has incomplete type" (now you
only have to understand that "incomplete type" refers to the type
having only been pre-declared).

Can anyone think of a drawback of doing this?
Ok, I can't see that you gain anything from this.
If you have double include guards, you have them.
If you don't have them, then adding this forward
declaration does not seem to gain you anything.
Socks

Jul 5 '07 #2
On Jul 5, 7:30 pm, Juha Nieminen <nos...@thanks.invalidwrote:
Multiple inclusion of the same header file can cause the compilation
to fail because of multiple definitions of the same type. That's why
it's standard practice to write all headers like this:
// SomeClass.hh
#ifndef SOME_CLASS_HH
#define SOME_CLASS_HH

class SomeClass
{
...
};
#endif
In complex projects recursive inclusion happens. It can be a rather
long chain of headers including other headers in a loop, and it may
be easy to miss.
The problem is that when this happens, the compiler errors are
usually very confusing. In the worst case (this has happened to me)
the compiler starts giving errors on places which have so far
compiled without problems and you haven't touched for weeks. It can
easily be really confusing why the compiler suddenly started to
complain about something you haven't even modified. Unless you have
experienced it before, it can be really hard to guess that the
problem is in a recursive inclusion which formed when you wrote
that one #include in a seemingly unrelated header. (Depending on
the compiler and the project settings it may be completely unexpected
what will "break" first because of that.)
I was thinking: In most cases when this problem has happened to me,
it was easy to fix by removing the #include and replacing it with a
pre-declaration of the class, as this usually has happened only when
I use references/pointers to that class instead of instances. Thus if
all headers were written like this:
// SomeClass.hh
class SomeClass;
#ifndef SOME_CLASS_HH
#define SOME_CLASS_HH
class SomeClass
{
...
};
#endif
then recursive inclusion would not be a problem. If you are only
using pointer/references, then everything will compile and work ok.
And even if you are using the class as a member variable and you
simply can't do that, you will most probably get a more meaningful
error message, like "error: field `x' has incomplete type" (now you
only have to understand that "incomplete type" refers to the type
having only been pre-declared).
Can anyone think of a drawback of doing this?
Compile times will shoot up, since the typical optimization of
not re-opening a file protected by include guards won't work.

It masks, rather than corrects, a real problem.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jul 6 '07 #3
Puppet_Sock wrote:
Ok, I can't see that you gain anything from this.
If what you are using is only references/pointers to the class,
the program will compile ok regardless of the recursive inclusion.
Jul 6 '07 #4
James Kanze wrote:
Compile times will shoot up, since the typical optimization of
not re-opening a file protected by include guards won't work.
You mean some compilers do that automatically? Which ones?
Jul 6 '07 #5
On Fri, 06 Jul 2007 12:48:56 +0300, Juha Nieminen wrote:
James Kanze wrote:
>Compile times will shoot up, since the typical optimization of not
re-opening a file protected by include guards won't work.

You mean some compilers do that automatically? Which ones?
gcc definitely does it.

--
Markus Schoder
Jul 6 '07 #6
On Jul 7, 1:20 am, Markus Schoder <a3vr6dsg-use...@yahoo.dewrote:
On Fri, 06 Jul 2007 12:48:56 +0300, Juha Nieminen wrote:
James Kanze wrote:
Compile times will shoot up, since the typical optimization of not
re-opening a file protected by include guards won't work.
You mean some compilers do that automatically? Which ones?
gcc definitely does it.
gcc has been doing it for years. If others haven't followed
suite, they're asleep on the job. It's really not difficult.

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jul 7 '07 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: JP SIngh | last post by:
Thanks to Manohar for writing the basic code for displaying the managers and the employees in a tree like structure. I have adapted the code below but it gives me an error "exception occcured"...
1
by: Ali Asghar | last post by:
Hi, Please I need help.I have a problem of client side XSL transformation. I sent the XML and the XSL to the client in XML data islands. Using the transform Node method the HTML is returned....
11
by: Alexander Stippler | last post by:
Hi, I have a little problem to design some template classes in a realizable way. I have some Container classes and some Proxy classes (proxies for elements). Looks like this: // P is the...
4
by: Kristian | last post by:
This is my document body content: <div id="nodeTree" class="nodeTree" title="nodeTree"> <div id="Hovedside" title="Hovedside" class="branch"> Hovedside <div id="Produkter" title="Produkter"...
2
by: krema2ren | last post by:
Hi I've the following header problem that I need two classes to know each other through a boost::shared_ptr. Does any of you smart guys have a solution? A.h ---------------------- #include...
2
by: Pindare | last post by:
Hello, I wrote quite a few c++ programs a some years ago which I compiled successfully with g++ at the time, but now I forgot how to make them work, so your help would be greatly appreciated (I...
1
by: Alkimake | last post by:
here is the code that i am using for recursion to view the tree of my database records. recurs(48); $i =0; function recurs($ownerid) { global $i; $sqlOne="SELECT * FROM sub_cat WHERE...
1
by: RajinCodingForum | last post by:
I have some idea but i am puzzled. As i understand, file inclusion problems like x includes y and y in turn includes x etc. can be avoided by #ifdef preprocessor checks. Can you please explain with...
1
by: xoinki | last post by:
hi all, I have 3 classes. class A, class B, and class C, class D, defined in 4 files A.cpp, B.cpp, C.cpp, D.cpp inheritence hierarchy is as follows. A--> B --> C | | ...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.