I was using forward declaration and includes in one small project.
But sometimes if i created a file.
A that includes C and D.
And then include in B the A, C, D i had some problems, i added the forward declaration to it.
I noticed, that sometimes i just need the forward declaration, it happens because when i previous added it to a file that i includes in the file where the forward declaration is?
Like if i just include in B the A, so the C and D is included too?
I have an class where i just needed to add the forward declaration.
Like:
Class a;
Class b;
Class R{
}
then the file a included the R, so i didn't need to include the a in R, if i did that the code didn't compile. It says something like to declare a class before the {.
Other case is:
A forward declare B, but dont include B and B include A.. it works, i imagine that its because the time the compiler "paste" the A code in B, the forward declaration tells the compiler that the class is there down in the code. If i use ifdef/ifndef and include code b in a it crashes, if i remove the include it works as a charm ^^
Thanks.
Unless you are introducing circular dependencies, which can be broken with forward declarations, just use an #ifndef / #endif pair:
#ifndef _FILE_H_
#define _FILE_H_
/* ... header file specifications ... */
#endif /* _FILE_H_ */
I am too tired to think about all the dependencies you have there, but remember that #include is nothing more than insertion of included file exactly into the place of #include. This is done recursively until all #include directives are expanded.
It is also good to guard against multiple insertions of the same file by typical
#ifndef FILE_H
#define FILE_H
...
#endif
Related
Suppose I have two data structures that reference each other. I want to put them into their separate header files like this:
// datastruct1.h
#ifndef DATA_STRUCT_ONE
#define DATA_STRUCT_ONE
#include <datastruct2.h>
typedef struct DataStructOne_t
{
DataStructTwo* two;
} DataStructOne;
#endif
and
// datastruct2.h
#ifndef DATA_STRUCT_TWO
#define DATA_STRUCT_TWO
#include <datastruct1.h>
typedef struct DataStructTwo_t
{
DataStructOne* one;
} DataStructTwo;
#endif
and I have a main function:
#include <datastruct1.h>
#include <datastruct2.h>
int main()
{
DataStructOne* one;
DataStructTwo* two;
}
However my compiler complains:
$ gcc -I. -c main.c
In file included from ./datastruct1.h:4,
from main.c:1:
./datastruct2.h:8:2: error: unknown type name ‘DataStructOne’
8 | DataStructOne* one;
| ^~~~~~~~~~~~~
Why is that? What can I do to fix this?
Why?
In order to understand why, we need to think like a compiler. Let's do that while analysing main.c line by line. What would a compiler do?
#include <datastruct1.h>: Put "main.c" aside (push to the stack of files being processed) and switch to "datastruct1.h"
#ifndef DATA_STRUCT_ONE: hmm, this is not defined, let's continue.
#define DATA_STRUCT_ONE: OK, defined!
#include <datastruct2.h>: Put "datastruct1.h" aside and switch to "datastruct2.h"
#ifndef DATA_STRUCT_TWO: hmm, this is not defined, let's continue.
#define DATA_STRUCT_TWO: OK, defined!
#include <datastruct1.h>: Put "datastruct2.h" aside and switch to "datastruct1.h"
#ifndef DATA_STRUCT_ONE: this is now defined, so go straigh to #endif.
(end of "datastruct1.h"): close "datastruct1.h" and pop current file from the stack of filles. What were I doing? Ahh, "datastruct2.h". Let's continue from the place where we left.
typedef struct DataStructTwo_t ok, starting a struct definition
DataStructOne* one; Wait, what is DataStructOne? We have not seen it? (looking up the list of processed lines) Nope, no DataStructOne in sight. Panic!
What happened? In order to compile "datastruct2.h", the compiler needs "datastruct1.h", but the #include guards in it "datastruct1.h" prevent its content from being actually included where it's needed.
The situation is symmetrical, so if we switch the order of #include directives in "main.c", we get the same result with the roles of the two files reversed. We cannot remove the guards either, because that would cause an infinite chain of file inclusions.
It appears that we need "datastruct2.h" to appear before "datastruct1.h" and we need "datastruct1.h" to appear before "datastruct2.h". This does not seem possible.
What?
The situation where file A #includes file B which in turn #includes file A is clearly unacceptable. We need to break the vicious cycle.
Fortunately C and C++ have forward declarations. We can use this language feature to rewrite our header files:
#ifndef DATA_STRUCT_ONE
#define DATA_STRUCT_ONE
// No, do not #include <datastruct2.h>
struct DataStructTwo_t; // this is forward declaration
typedef struct DataStructOne_t
{
struct DataStructTwo_t* two;
} DataStructOne;
#endif
In this case we can rewrite "datastruct2.h" the same way, eliminating its dependency on "datastruct1.h", breaking the cycle in two places (strictly speaking, this is not needed, but less dependencies is always good). Alas. this is not always the case. Often there is only one way to introduce a forward declaration and break the cycle. For ecample, if, instead of
DataStructOne* one;
we had
DataStructOne one; // no pointer
then a forward declaration would not work in this place.
What if I cannot use a forward declaration anywhare?
Then you have a design problem. For example, if instead of both DataStructOne* one; and DataStructTwo* two; you had DataStructOne one; and DataStructTwo two;, then this data structure is not realisable in C or C++. You need to change one of the fields to be a pointer (in C++: a smart pointer), or eliminate it altogether.
One way to resolve the circular dependency and still use the typedefs where possible is to split the headers into two parts with a separate guard macro for each part. The first part provides typedefs for incomplete struct types and the second part completes the declarations of the struct types.
For example :-
datastruct1.h
#ifndef DATA_STRUCT_ONE_PRIV
#define DATA_STRUCT_ONE_PRIV
/* First part of datastruct1.h. */
typedef struct DataStructOne_t DataStructOne;
#endif
#ifndef DATA_STRUCT_ONE
#define DATA_STRUCT_ONE
/* Second part of datastruct1.h */
#include <datastruct2.h>
struct DataStructOne_t
{
DataStructTwo *two;
};
#endif
datastruct2.h
#ifndef DATA_STRUCT_TWO_PRIV
#define DATA_STRUCT_TWO_PRIV
/* First part of datastruct2.h. */
typedef struct DataStructTwo_t DataStructTwo;
#endif
#ifndef DATA_STRUCT_TWO
#define DATA_STRUCT_TWO
/* Second part of datastruct2.h */
#include <datastruct1.h>
struct DataStructTwo_t
{
DataStructOne *one;
};
#endif
main.c
/*
* You can reverse the order of these #includes or omit one of them
* if you want.
*/
#include <datastruct1.h>
#include <datastruct2.h>
int main(void)
{
DataStructOne *one;
DataStructTwo *two;
}
As mentioned in the comment in main.c above, only one of the headers needs to be included since the other header will be included indirectly anyway.
Well, if both structures reference each other, it is clear that they must be related. The best thing you can do is to put both in one include file (as they are related) but putting them in different and making the compiler to read from one include the other will make the compiler to read the main file... .from main file start reading include A until it gets to the point to include B, and start reading B to the point of the include A again(we'll start reading A again in a recursive manner that has no end) you will never stop reading each file and worse, you will get an error the second time you see the same struct definition (because it has been already defined before)
To allow the user to include any or both files without a problem, a define is made when include file A is encountered:
File A.h
#ifndef INCLUDE_FILE_A
#define INCLUDE_FILE_A
/* ... the whole stuff of file A with the proper includes of other files.*/
#include "B.h"
#endif /* INCLUDE_FILE_A */
and in
File B.h
#ifndef INCLUDE_FILE_B
#define INCLUDE_FILE_B
/* ... the whole stuff of file B with the proper includes of other files.*/
#include "A.h"
#endif /* INCLUDE_FILE_B */
so the definitions made in file A are only used if INCLUDE_FILE_A has not been included previously, and skip them if file A has been included already (and the same for B.h, of course).
If you make the same on file B (but instead with INCLUDE_FILE_B) then you will be secure that both files will be included in either order (depending on how you did it in the first case) and will never be included again (making th e inclussion secure of returning back to the main file.
I am working on a clock display assignment and my professor wants us to use two classes, NumberDisplay and ClockDisplay. So in total I have two header and three cpp files. When I implemented the first part of the assignment using just the first class everything was fine. I noticed though that my professor wants us to declare a NumberDisplay object inside our ClockDisplay header. I figured just declaring like normal would work like this NumberDisplay hours = NumberDisplay(24); however I am not able to access the information unless I include the NumberDisplay.h file for my ClockDisplay.h. When I do that however I am assuming my errors are due to using #include <NumberDisplay.h> in both my NumberDisplay.cpp and my ClockDisplay.cpp. I just would like to know the proper way to structure my files so that I can properly create NumberDisplay objects in my ClockDisplay header file and then use said objects in my ClockDisplay cpp file.
You can #include "NumberDisplay.h" within ClockDisplay.h. This will allow you to use NumberDisplay objects within your ClockDisplay's class declaration.
As a side note, be sure to use include guards for your headers. This will prevent the header from being included multiple times during compilation. Use #pragma once or
#ifndef NUMBERDISPLAY_H_
#define NUMBERDISPLAY_H_
...
#endif // NUMBERDISPLAY_H_
As user Sean Monroe pointed out about using header or include guards; this may not always be the full answer. This will help in many cases to fix your current problem but if you are not careful you can become a victim of circular includes.
Before I mention anything about that I will briefly describe the differences between #include <someheader.h> and #include "someheader.h". The first one will look where most of your system, os, and compiler and standard libraries files are located through the use of system environment variables that are setup by default through your IDE. The later will look in any immediate directories that are setup in the include paths for the current project with the root path being where the code lives when it is created if working in Visual Studio; other IDE's will more than likely be different, but the concept is still the same.
On circular includes: sometimes having header guards alone is not enough. Take for example:
file a.h
#ifndef A_H
#define A_H
#include "b.h"
class A {
private:
B b;
public:
explicit A( const B& b ) { ... }
};
#endif
file b.h
#ifndef B_H
#define B_H
#include "A.h"
class B {
public:
explicit( A* pA ) { ... }
};
#endif
Here this would generate a circular include and this is something that is very important to be aware of. Regardless of which class A or B you try to create an object of in some other file, namespace, class or function the compiler will try to construct the first class and in order to do so it needs to construct the second class however when trying to construct the second class to complete the first class it goes back and tries to construct the first class again since the next requires the first which is an incomplete object and visa versa. This is not exactly a circular include per say but it is a circular infinite recursion of dependencies of incomplete classes. You can read this Q/A for more information: Resolve Circular Dependencies.
Sometimes it is not enough to just include the appropriate header of one class into the header of another; sometimes you may need to just declare a class prototype and or forward declaration in a class's header then include the header file within that class's cpp file. But this will usually work most often with pointers or references but not local copies since pointers and references are addressed by memory location that have a fixed size in memory. Example:
file A.h
#ifndef A_H
#define A_H
class B;
class A {
private:
B* pB;
public:
explicit A( const B& b );
};
#endif
file A.cpp
#include "A.h"
#include "B.h"
A::A( const B& b ) { ... }
file B.h
#ifndef B_H
#define B_H
#include "A.h"
class B {
public:
B(){ ... }
/*param type*/ someFunc( A* pA ) { /* do something with pA */ }
};
There are more problems than what are discussed here but you can read about them in some of the other answers to the same link that I provided above.
I am getting stuck using this class, when I used in the main.cpp there is no problem and execute perfectly, but when I use it as a member class the compiler doesn't like it and sends the message "Multiple definition of:"
Here is the class:
RTPSocket.h:
#ifndef RTP_SOCKET_HDR
#define RTP_SOCKET_HDR
namespace RTPConnection
{
enum EMode
{
Sender,
Receiver
};
template<EMode Mode>
class RTPSocket
{
};
}//end namespace
#define RTP_SOCKET_IMP
#include "RTPSocket_Imp.h"//file where i declare the implementation code
#undef RTP_SOCKET_IMP
#endif
this class by itself doesn't have any problem but when i use it in my class, but ....
used in another class
my file.h
#include RTPSocket.h
class CommClass
{
private:
RTPSocket<RTPConnection::Receiver> * mRTPServer;
}
the compiler give this error message:
multiple definition of 'enum RTPConnection::EMode'
this is a method that is declared in another file "rtpsocket_imp.h"
with the guard declared:
template<EMode Mode>
void RTPSocket<Mode>::write(char* aArray,
const size_t aiSize)
{
std::string message("The write function is operative only on Sender Mode");
throw BadTemplate(message);
}
You want include guards around the header:
#ifndef RTPSOCKET_H
#define RTPSOCKET_H
// header contents go here
#endif
This will prevent the header contents from being included more than once per source file, so you will not accidentally get multiple definitions.
UPDATE: Since you say you have include guards, then possible causes of the error might be:
misspelling the include guard name, so it doesn't work
defining something with the same name in another header (or the source file that includes it)
undefining the include guard name.
But without seeing code that reproduces the error, I can only guess what might be wrong.
You need an include guard.
Inside the RTPSocket.h file at the top put
#ifndef RTPSOCKET_INCLUDED
#define RTPSOCKET_INCLUDED
and at the end put
#endif
If that's not the problem, and you do have an include guard, I suggest you search for
enum EMode
in your code and find all the places you have defined it, and make sure you just define it once.
My problem was the CMakeLists.txt that was building this project.
My fault!
placeable.h
#include "selectable.h"
class placeable : selectable
{
..
};
selectable.h
#include "game.h"
class selectable
{
..
};
game.h
#include "placeable.h"
class game
{
...
class placeable* holding;
...
};
Basically placeable.h includes selectable.h which includes game.h which includes placeable.h again.
The only solution i can think of is placing the placeable* in a new header, making it static/global and then include this new header in game.h and selectable.h.
I'm sorry i dint include header guards in the upper code. I assumed it was obvious.
Header guards does not help in this case because of the inheritance, same thing goes with forward declaring.
Only include headers if you MUST
Use forward declaration in preference to including:
You only need to include the header for class X iff:
You have a member of the class 'X'
You derive from the class 'X'
You pass a parameter of class 'X' by value.
Otherwise a forward declaration will suffice.
// -> Don't do this #include "placeable.h"
class placeable; // forward declare
// Fine if you are using a pointer.
class game
{
...
class placeable* holding;
...
};
PS. Add header guards.
This means you have not properly encapsulated the functionality of your design. It should be higher-level includes lower level, not same-level includes same-level. If game is the higher level then selectable should not include game.h.
This is a solved problem. It's called header guards. Try this inside ALL of your header files:
#ifndef __NAMEOFTHEFILE_H__
#define __NAMEOFTHEFILE_H__
// nothing goes above the ifndef above
// everything in the file goes here
// nothing comes after the endif below
#endif
Also, you can do this (this is known as a forward reference):
// game.h
class placeable;
class game { ...
placeable* p;
};
There are two problems:
Circular headers dependency. Solution - #ifndef ...
Allocating space for unknown type. Solution - class placeable;
See more here
Use header guards in each of your header files to avoid this problem. In general, your header files should like this:
#ifndef PLACEABLE_H
#define PLACEABLE_H
//
// Class definitions and function declarations
//
#endif
#include "DLLDefines.h"
#include "DLLDefines.h"
The above actually passed compilation, but why?
Well, it's legal because it has to be legal. Because you often include the same header multiple times without even realizing it.
You might include two headers in a .cpp file, each of which include a number of files, some of which might be included by both.
For example, all the standard library headers (say, string or vector for example) are probably included in most of your headers. So you quickly end up with the same header being indirectly included multiple times in the same .cpp file.
So in short, it has to work, or all C++ code would fall apart.
As for how it works, usually through include guards. Remember that #include just performs a simple copy/paste: it inserts the contents of the header file at the #include site.
So let's say you have a header file header.h with the following contents:
class MyClass {};
now let's create a cpp file which includes it twice:
#include "header.h"
#include "header.h"
the preprocessor expands this to:
class MyClass {};
class MyClass {};
which obviously causes an error: the same class is defined twice. So that doesn't work. Instead, let's modify the header to contain include guards:
#ifndef HEADER_H
#define HEADER_H
class MyClass {};
#endif
Now, if we include it twice, we get this:
#ifndef HEADER_H
#define HEADER_H
class MyClass {};
#endif
#ifndef HEADER_H
#define HEADER_H
class MyClass {};
#endif
And this is what happens when the preprocessor processes it:
#ifndef HEADER_H // HEADER_H is not defined, so we enter the "if" block
#define HEADER_H // HEADER_H is now defined
class MyClass {};// MyClass is now defined
#endif // leaving the "if" block
#ifndef HEADER_H // HEADER_H *is* defined, so we do *not* enter the "if" block
//#define HEADER_H
//
//class MyClass {};
//
#endif // end of the skipped "if" block
So, the end result is that MyClass got defined only once, even though the header was included twice. And so the resulting code is valid.
This is an important property of header files. Always define your headers so that it is valid to include them multiple times.
It depends on the header file; there is no language restriction on multiple includes of the same file.
Some files are designed to be included multiple times (e.g. <assert.h> can be included multiple times to turn 'on' and 'off' assert).
Many files are safe to be included multiple times because they have include guards, others are not and should be included only once in a translation unit or even a program.
include has nothing to do with the C or C++ language. It is a directive to the preprocessor to bring in a file. The preprocessor doesn't care what file is brought in and it shouldn't. It might be perfectly acceptable to do this:
void Foo::SomeFunc(int cond)
{
switch (cond) {
case kThisCase:
#include "longFirstCase.h"
break;
case kSecondCase:
#include "longSecondCase.h"
break;
case kThirdCase:
#include "longFirstCase.h"
#include "longSecondCase.h"
break;
}
}
I have seen the same file included several times as a configuration mechanism as well.
Granted, there are a number of ways to factor that example that are better, but the point is that there may be perfectly good reasons why you would want to and therefore no restriction on the use.
Probably you have some #define in DLLDefines.h around your code that prevents it from being included twice.
#ifndef DLLDEFINES_H
#define DLLDEFINES_H
// your code
#endif
As long as the multiple inclusion of header files do not violate ODR (One definition Rule) $3.2, the code is well-formed.
It's called an include guard.
#ifndef GRANDFATHER_H
#define GRANDFATHER_H
struct foo {
int member;
};
#endif
Quote from Wikipedia:
In the C and C++ programming languages, an #include guard, sometimes called a macro guard, is a particular construct used to avoid the problem of double inclusion when dealing with the #include directive. The addition of #include guards to a header file is one way to make that file idempotent.
See link above for more information.
DLLDefines.h may also have #pragma once at the
top, #pragma once ensures that file gets included only once.