I want to make a project, have 3 files:
main.cpp
header.h
declerations.cpp where i have all the function declarations.

But I'm not sure how to link them all together.
When I make a header file, it automatically types the #ifndef header_h but I thoguht that should be in the declerations.cpp??

Let's say I have 3 files:
main.cpp

//main.cpp
#include <iostream>

int main()
{
test();

return 0;
}
}

header.h

//header.h
void test();

and declerations.cpp

//declerations.cpp
void test()
{
 cout <<"This is from the function test in declerations.cpp";
}

But how should the linking look (where should I have my #includes? should i include both declerations and header to the main.cpp? or...? :///)

I was told that you need the #ifndef so that you don't declare the same thing twice.
But shouldn't you use #ifndef on everything then? for example iostream?

Recommended Answers

All 13 Replies

>>But how should the linking look (where should I have my #includes? should i include both declerations and header to the main.cpp? or...? :///)
It is extremely rare that you would have to #include a *.cpp file in another file. You would #include your header file in both *.cpp files:

//myClass.h
class myClass {
  //...
};
//myClass.cpp
#include "myClass.h"

//...
//main.cpp
#include "myClass.h"

int main() {
  //...
}
//...

The problem is, as this is written, you will get a "redefinition" error. To prevent this, you need to guard your header...

>>I was told that you need the #ifndef so that you don't declare the same thing twice.
This is true. The "#ifndef" stuff are what are called "include guards". They work by causing the header file to only exist one time within your code. They are designed to prevent the header being included more than once.

//myClass.h
#ifndef MY_CLASS_H
#define MY_CLASS_H

class myClass {
  //...
};

#endif //end MY_CLASS_H guard

>>But shouldn't you use #ifndef on everything then? for example iostream?
Emphatically NO! You can place them in your *.cpp files, but it's not a good way to do it. They are best placed within the header file because that's what they're "guarding". By placing them in the header they are guarding, they travel with the header so that you don't have to handle the guarding yourself every time you need the header.

If you open your <iostream> header, you'll find guards in that file. The guards will be one or both of 2 possibilities:

#pragma once

or

#ifndef _IOSTREAM_
#define _IOSTREAM_

//...

#endif /* _IOSTREAM_ */

So, it's already been guarded for you. This is why it's best to do it in the header, not the implementation (*.cpp) file.
WARNING: While you have this file open, do not make any changes and do not save any changes if prompted.

How you would need to do it is as follows (explanation will follow):

//header.h
#ifndef HEADER_H
#define HEADER_H

void test();

#endif
//main.cpp
#include <iostream>
#include "header.h"   //to find the test() function.

int main()
{
  test();

  return 0;
}
//declerations.cpp
#include "header.h"

#include <iostream> //for using std::cout.

void test()
{
  std::cout << "This is from the function test in declerations.cpp";
}

Each cpp file is what we formally call a "translation unit". They are compiled separately and then linked together. So, since each cpp is compiled separately, they need to #include all the headers that they need for the compilation to work (thus the #include <iostream> and "header.h" in both the main.cpp and declarations.cpp).

Since cpp files are compiled separately and alone, they will never be "included" twice in one compilation run (in one "translation unit"). So, the header-guards (i.e. the #ifndef HEADER_H) are not required for cpp files because their content are guaranteed to appear only once. For header files, this is not the case, and header-guards are needed. Imagine this simple situation:

//in header1.h
int global_value = 10;

//in header2.h
#include "header1.h"

//in main.cpp:
#include "header1.h"
#include "header2.h"    //which will, in turn, include "header1.h" a second time.

int main() {
  return global_value; //ERROR: Which "global_value" should be used? there are two declarations of the same variable, this will not compile due to the One-Definition-Rule in C/C++.
};

Because headers are meant to be included by different files (other headers or cpp files) there is no way to ensure that a particular header won't get included more than once. The header-guards guarantees that the _content_ of the header will only be looked at by the compiler once.


Finally, how to compile and link your application together. There is the quick and simple way (assuming you use GCC):

$ gcc -Wall main.cpp declarations.cpp -o my_app.exe

This says to compile both translation units "main.cpp" and "declarations.cpp" with all warnings enabled (-Wall) and output them (-o) (linked together) as an executable named "my_app.exe". You can also compile each translation unit separately into object files (.obj or .o) and then link them together as an executable, but the above is simpler.

commented: Nicely described the answer. Really easy to understand +3
//myClass.h
#ifndef MY_CLASS_H
#define MY_CLASS_H

class myClass {
  //...
};

#endif //end MY_CLASS_H guard

Just one question.
Shouldn't it be like

//myHeaderFile.h
#ifndef myHeaderFile_h
#define myHeaderFile_h
#include "myHeaderFile_h"
#endif

?

No.
What they said is correct.

Just one question.
Shouldn't it be like

//myHeaderFile.h
#ifndef myHeaderFile_h
#define myHeaderFile_h
#include "myHeaderFile_h"
#endif

?

No. When done properly, the guards are already in place in the header. They are not needed in the #including location. It's redundant, not to mention dangerous. If they're not correctly done, by the time the compiler gets there, the damage has already occured. Assuming the compiler does get to that point, and your header file has a proper guard in it if you happen to use the same #define for the guard in the *.cpp file, you won't get your header information because it will break the #include directive by triggering the guard in the header.

EDIT:
Oops, where'd Walt come from??

commented: I'm sneaky :oP +16


Finally, how to compile and link your application together. There is the quick and simple way (assuming you use GCC):

$ gcc -Wall main.cpp declarations.cpp -o my_app.exe

This says to compile both translation units "main.cpp" and "declarations.cpp" with all warnings enabled (-Wall) and output them (-o) (linked together) as an executable named "my_app.exe". You can also compile each translation unit separately into object files (.obj or .o) and then link them together as an executable, but the above is simpler.

I'm using CodeBlocks.
So after i compile the project, I can just send the .exe file?

And if you dont mind: What the hell is DLL then?
If someone sends you their program it usually(?) has 1 or a few .exe and a bunch of dlls and maybe a little more stuff - not a .h file or .cpp?

No. When done properly, the guards are already in place in the header. They are not needed in the #including location. It's redundant, not to mention dangerous. If your header file has a proper guard in it and you happen to use the same #define for the guard in the *.cpp file, you won't get your header information because it will break the #include directive by triggering the guard in the header.

EDIT:
Oops, where'd Walt come from??

//header.h

#ifndef HEADER_H
#define HEADER_H

 void test();
  
#endif

So this will check if "header_h" is defined... and if it isn't it will define it and... and define the void test() ?
Did I get it right?

>>So this will check if "header_h" is defined... and if it isn't it will define it and... and define the void test() ?
Did I get it right?
Yes.

>>what is a DLL
A DLL is a "shared library"; it's a type of support file. It is "linked" to by the main program executable at run-time; it contains functions, classes, variables, etc. that are used by the main part of the program.

>>So this will check if "header_h" is defined... and if it isn't it will define it and... and define the void test() ?
Did I get it right?
Yes.

>>what is a DLL
A DLL is a "shared library"; it's a type of support file. It is "linked" to by the main program executable at run-time; it contains functions, classes, variables, etc. that are used by the main part of the program.

So... the "declerations.cpp" could be turned into a .dll instead?
Because that contains the functions and stuff that the main.cpp uses

No, a DLL is the result/output of the compilation and linking process, not compilable source code. It's a type of output file, just like a *.exe file.

If you compile your project correctly (as per mike's directions/example), your "declarations.cpp" file will automatically be compiled, and linked with, your "main.cpp" (or whatever it's called) to produce the final *.exe file. There should be no other files needed.

Both a DLL and an EXE are called "modules". When code gets compiled, you get a bunch of functions compiled to executable code and collected together in a module. In the case of an executable, there is one special function (the "main()" function) which is called the "entry-point" because when you run the program, that function gets called and that starts the execution of your program. In a DLL, there is no such function (well, there is, but let's not get into that). In that sense, a DLL is just an executable without an entry-point, thus, it cannot be executed directly. However, an executable program can use a DLL and call the compiled functions that are contained in it. DLLs are called either "shared libraries" or "Dynamic Link Libraries" which emphasizes two different characteristics that they have. They are shared because you can group many functions that could be useful to many different applications into one DLL and then different applications can share that DLL and its set of functions without the need for recompilation from source. It is dynamically linked which means that the linking (similar to what happens when you compile different "translation units" and _link_ them together to form an executable) is performed at run-time, either by loading the DLL when the executable starts (called static loading) or by loading it manually in the code of the application (via some system call like LoadLibrary()) at whichever point you like to load it (called dynamic loading). Creating and using DLLs is not really all that easy because there are several special considerations to take into account, you shouldn't venture into that until you have much more knowledge about programming and some of the intricate details. Stick to simple executable-only programs for now.

They are shared because you can group many functions that could be useful to many different applications into one DLL and then different applications can share that DLL and its set of functions without the need for recompilation from source.

Correction. Sharability is a runtime property. A static library also requires no recompilation. The difference is that if you run two (or more) applications statically linked to the same library, you'd end up with two (or more) copies of the library code. If the library is shared, all applications share the same single image of its code.

@nezachem: True. I was just putting things in Lay-man's terms and trying not to open the flood-gates to explaining everything.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.