# Help me understand .cpp vs .h in C++

This topic is 1761 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

#ifndef LEVEL_H_INCLUDED
#define LEVEL_H_INCLUDED

#include "sdl_functions.h"

class Level {
public:
Level();

int width, height;
int map_grid[20][20];

void display_grid();
};

#endif // LEVEL_H_INCLUDED


Separate your .h and .cpp files again and use the version I have posted. Does this help any? Or change any of the errors?

##### Share on other sites

TTFN

Edited by Poigahn

##### Share on other sites

class Level {
public:
Level();

public :

class Level{....

This makes this Class Public to the calling program

class Level{

public:

Level()

only makes this class public inside the current header file, as in your second example.

This is simply wrong. public, private and protected only take effect inside classes and/or structs, a class is always "public" where you include it. So he got that one right.

@Topic:

    #ifndef LEVEL_H_INCLUDED
#define LEVEL_H_INCLUDED

#include "sdl_functions.h"

...

#endif // LEVEL_H_INCLUDED


You can simply put "#pragma once" at the top of your header file. Make sure everything is included beyond that, then your errors should be solved.

Edited by The King2

##### Share on other sites

TTFN

Edited by Poigahn

##### Share on other sites

This is a hard topic unless you know just a bit about what's going on behind the scenes when compiling. What happens is basically the compiler looks at what .cpp files you have in the project (or folder or the ones you tell it to compile, this depends), turns each one of them into an object file (.obj with visual studio, .a and .o also exist with some compilers IIRC) and it's done. After this the linker jumps onto the scene and starts looking at what pieces of code it needs to make the program into an actual executable - this is why you, for example, tell the linker, not the compiler, where the execution starts. Here you can have so called statically linked libraries too, that's the list of .lib files you feed to your linker. The most usual linker errors occur when you either forget to link against something or have multiple definitions - the same variable or function exists in several object files and the linker can't figure out which one to use.

Now, you might notice I didn't mention headers at all. This is because a header is never compiled itself, it's just included into (usually several) other files. So if your header has a global variable definition (for example "int x = 5;"), it'll be in all of the .cpp files and the linker won't like this. So you want your headers to only hold declarations, not definitions. int foo(int x); is okay, int foo(int x){return x*2+1;} isn't. Unless it's code you only use in one file, though then you don't even have to keep it in the header at all.

Edited by powly k

##### Share on other sites

This is kind of a tricky thing to explain, but when you understand it, you will understand how executables and libraries work much better. The solution to your problem has already been posted, but if you want the long explanation of what's going on, here it is! The main thing you need to understand is how the compiler and the linker work together. Pay close attention to the words declare and define.

The compiler turns all your source code into object files (as mentioned earlier), which contain actual executable code (basically). For each method, a callable segment of machine code is created. However, within most functions, there are also calls to other functions. Since there is no need to reproduce the called function (inline functions excepted), a dependency is created on the code of the called function. So for instance, the first two lines of following function will be compiled, but one external dependency exists.

foo.cpp

void foo() {
int x = 0;
x = x + 2;
bar(x);
}

You will have a compilation error if this was the entirety of the source file, since bar(int) is never declared or defined. So, either you must define it in this source file, or declare it with a prototype with the signature bar(int). Here's where the linker comes in:

Suppose bar(int) is defined in another source file. You need a way of telling the compiler not to worry about it right now, but that it can count on it existing when the final executable is being built (it's the linker's job to connect unresolved functions/variables to their instantiations), so that's what a header file does:

bar.h

#pragma once
void bar(int x);

We have now declared bar(int). We now need to look at foo.h:

#pragma once
#include "bar.h"
void foo();

And of course we need to include foo.h in foo.c (I didn't show that earlier since I wanted to make sure that it would be understood that the compiler would have no way of knowing that bar(int) existed at that point). So, what happens is that the compiler is told: 'there will be a method with the signature bar(int)', so you can make that call in the code. Now, as far as we've gotten, we still haven't defined bar(int), so if we tried to build as is, the compilation process would go fine, but we would get an unresolved external symbol: ...bar(int) from the linker. The reason is that the linker's job is to find all the unresolved calls and resolve them. This means: find the compiled code for bar(int) and actually jump to it ('link' it). To fix the problem, we must define the function with the matching signature:

bar.cpp

#include "bar.h"
void bar(int x) { x++; } // now we've generated some code for the linker to 'link' the previously unresolved dependency to

Now the code compiles and links. So, we've covered half of your problem, the other half is that the linker was unable to resolve the external variables that you were trying to access. So, if you understand everything so far, it's just more of the same. An extern variable means that the compiler will allow usage of a variable without actually knowing anything about it (starting with a new set of code):

foo.h:

#pragma once
extern int foo;

foo.cpp:

#include "foo.h"
int foo;

bar.h:

#pragma once
#include "foo.h"

bar.cpp:

#include "bar.h"
void bar() {
foo = 5; // this can be resolved by the linker since we know about foo from foo.h through bar.h
}

We can see that foo is a global int that anything that includes foo.h is able to access. The linker resolves the variable when creating the final executable. Alpha_ProgDes gave the right way to fix your problem (since your source file would now know about the extern SDL_Surfaces, which would allow the function/variables to be used).

The reason your old code worked was lucky inclusion order. Depending on the order that things are compiled, you can cheat the system, but this is a dangerous way to go about things, as the build will become very fragile based on the order of inclusions (certain dependency graphs are also impossible using that method). Projects built like that may, in effect, have *one* source file (aka compilation unit, since #include literally inserts source into a file), so everything must be defined in the right order instead of the proper way where it doesn't matter, since you're using the compiler and linker correctly. One other advantage you'll find in a large project is that where you used to have to recompile the entirety of the source for any change you made (since it was in effect one compilation unit), now your project can compile *only* the source that has changed, which is really great (can you tell I learned all this the hard way?).

This also explains libraries. Libraries are just compiled code. The header files for a library are just there to let source code depend on the library, and the linker will find the code and resolve the dependencies. For dynamic libraries, the 'cannot resolve dependency' error will come at run-time (eg when you're missing a dll), but it's the same principle.

I've sadly left out quite a bit, and used C for brevity, but C++ works the same way. In short:

• functions/methods (code units with a particular signature), and variables with any particular name can only be *defined* once in a compilation unit. A compilation unit is the entirety of the code being compiled (ie after all the #included files are inserted to make one big 'unit')
• to get code to compile, there *must* be *either* a definition or a declaration within the compilation unit.
• any variable/function that is only declared (not defined) within a compilation unit *must* be resolved by the linker if it is used (ie you can declare something and never define it if you never try to use it anywhere).
• a declaration *must* be resolved for an executable to be generated. If the definition is not within the compilation unit, it is the linker's job to resolve the dependency.
Edited by giant city games

##### Share on other sites

Like I said I was not up on my CPP and also asked for help in clarification,  So I guess by trying and asking fo help you get knocked down.

This is why people do not try.

If you know CPR, or if you're a paramedic, it's cool to help a person who collapsed on the street.

I would think twice before electrocuting people, or going "scalpel!" when I don't really know what I'm doing.

Even if I just want to help, try at home first - it won't mess up other peoples' interpretation of "correct".

have been out of CPP for awhile and I am trying to get back into it.  I realize newer versions of CPP have changed and so has the format.

That part never changed, though.

Edited by SuperVGA

##### Share on other sites

A part of the confusion of .h(pp) files comes from the preprocessor, this is an important concept to grok for C++, but it isn't intuitive, especially if you come from a language where they don't exist or are much less prevalent.

Essentially the pre-processor is a process that runs on your program *BEFORE* it is compiled.

When the preprocessor runs, it scans through your code looking for pre-processor directives.  Those are the lines that start with the pound (#) symbol, such as #define #pragma or #ifdef.

Most of the time, the preprocessor is simply generating the code file that will be sent to the compiler.  Consider the following common scenario with the preprocessor:

#ifdef _WIN32

int i = 42;

#else

int i = 43;

#endif

The preprocessor see this directives, and if you are running on Windows the final result is:

int i = 42;

If you are running on any other platform, the result becomes:

int i = 43;

Similarly, thats how header guards work, when you encounter:

#ifndef _BOB_H

#define _BOB_H

#endif

The preprocessor starts processing this file, checks if _BOB_H has been defined, if it hasn't it continues as usual, defining the value _BOB_H.  Therefore, the next time this .h file is #included, it fails the test ( since _BOB_H was defined on the prior pass ) and skips the file.  #pragma once is a shorthand (slightly un-standard, but standard enough to use it freely ) for the exact same thing.

Finally back to #include "bob.h".

When the preprocessor runs through your code and see's the line

#include "bob.h"

It simply is opening that file and copying the contents into where it was included.

##### Share on other sites

TTFN

Edited by Poigahn

##### Share on other sites
You are mixing C++ up with Managed C++, C++/CLI, C++. NET or whatever the he'll Microaoft calls it these days.

cout is unchanged.

##### Share on other sites

I don't think people will gang up on you and give you a million -1 votes,

You want to re-think this one ?

Yeah, sorry, I was wrong. I think if you had edited your post and added the strikethrough I suggested, a large number of downvotes could have been mitigated. But I frequent these forums a lot more than I should, and maybe you don't frequent them as much, so you didn't see my suggestion until today. Seeing as this is the "For Beginners" forum, technical accuracy is imperitive, and I'm guessing that's one reason why a large number of downvotes have been given. To be honest, I think you've received too many downvotes (yes, it's incorrect technical information, but I think your attitude has been rather positive and you did preface it with a warning).

I would like to state that I was not entirely incorrect on my original post.  I was wrong yes.  And what happened was, since I have been out of it for sometime, had several languages crossed.
IN VB6, you have to declare a class as PUBLIC in order to share it between modules.  So I had my wires crossed there!
In PASCAL you have to predeclare shared functions/procedures prior to actually using each.  SO I had my wires crossed there.

Yeah, I guessed you might have been mixing languages.

C++ has been like this for decades... Granted, C++ wasn't standardized as a language until 1998, so if you learned C++ before 1998, it's possible you learned someone's custom flavor of C++.

Now I have a quetion,  If C++  Has Not Changed since 1998, then why is some code not recompiling in Visual Studio 2010 ?  A consol app written in Studio 6 or 2008 will not recompile in studio 2010.

Heh, you brought up Visual Studio 6. Visual Studio 6 was released in June 1998. C++ was first (officially) standardized in September (if I'm not mistaken) 1998. Which is one reason why Visual Studio 6 has several discrepancies from standard C++. Additionally, with each compiler release, bugs are fixed and "compiler extensions" are changed/added/removed (so a new compiler with better standards compliance might break old non-compliant code). And on top of all of this, I never said "C++ has not changed (ever)." I said "C++ has been like this" (where "this" is specifically referring to the whole public: syntax and meaning). C++ has changed several times. There was a new standard released in 2003, and again a new standard in 2011 (2003 introduced some minor changes, 2011 introduced some major changes). C++ has certainly changed over the years, but it has not changed in regards to the things we've discussed in our context.

Correct me,  And I am certain to hammered on this, but cout << has been replaced by Console Writeline  for console applications.

And correct you I shall. Console.WriteLine is Microsoft .NET stuff. std::cout << is C++. std::cout has not been replaced in any way by Console.WriteLine. They're entirely different things (Microsoft .NET is Microsoft's own framework and has nothing to do with standard C++). You've mixed things up again.

I'm not going to derail this thread anymore. I don't want chiranjivi's topic to go off track. If you want to discuss this more, I suggest starting a new thread (or PMing people if there's anyone in specific you want to talk to).

Edited by Cornstalks

##### Share on other sites
Hi all,

Many thanks for the posts, Cornstalks and giant city games especially for your detailed and informative breakdowns of what was going on. After reading your responses and googling a little more I think I have a much better grasp of things. The problem was defining functions/variables in the sdl_functions header and then trying to include the header at every point where they were required; not understanding what the header files did meant I didn't understand why this wasn't a good idea! I appreciate all the feedback and everyone's attempts to help.

##### Share on other sites

Hi there's, i think you can make a precompiled header like "stdafx.h" and include all sdl header there, then you can include this header to all of your program

some think like this :

stdafx.h

#ifndef STDAFX_H_INCLUDED
#define STDAFX_H_INCLUDED

//include all needed header after this line
#include "sdl_functions.h"

#endif // STDAFX_H_INCLUDED


level.h

#ifndef LEVEL_H_INCLUDED
#define LEVEL_H_INCLUDED

#include "stdafx.h"

//program class code/definition

#endif // LEVEL_H_INCLUDED


what you need to do is just include the precompiled liblary in all of your class definition file(.h)

hmm, i don't know is that would solve your problem but i just want to show you how i manage to include my external liblary and distribute it to all of my code

good luck

Edited by Fs02

##### Share on other sites

Hi there's, i think you can make a precompiled header like "stdafx.h" and include all sdl header there, then you can include this header to all of your program

some think like this :

stdafx.h

#ifndef STDAFX_H_INCLUDED
#define STDAFX_H_INCLUDED

//include all needed header after this line
#include "sdl_functions.h"

#endif // STDAFX_H_INCLUDED


level.h

#ifndef LEVEL_H_INCLUDED
#define LEVEL_H_INCLUDED

#include "stdafx.h"

//program class code/definition

#endif // LEVEL_H_INCLUDED


what you need to do is just include the precompiled liblary in all of your class definition file(.h)

hmm, i don't know is that would solve your problem but i just want to show you how i manage to include my external liblary and distribute it to all of my code

good luck

While stdafx.h is what it used for precompiled headers, and what you are suggesting is perfectly valid, you are mixing up your expressions a little bit.

A precompiled header is actually a compiler optimization, you need to enable it.  The idea is to include all the header files that don't change often and have the compiler compile them all once in advance.  This is where the "pre-compiled" part comes in.  That means the next time you compile your code, these header files wont have to be compiled, speeding the process up.

##### Share on other sites

While stdafx.h is what it used for precompiled headers, and what you are suggesting is perfectly valid, you are mixing up your expressions a little bit.

A precompiled header is actually a compiler optimization, you need to enable it.  The idea is to include all the header files that don't change often and have the compiler compile them all once in advance.  This is where the "pre-compiled" part comes in.  That means the next time you compile your code, these header files wont have to be compiled, speeding the process up.

Yupp, that's what i mean, thanks for making it clear

##### Share on other sites

I dont think its a good idea to tell someone who barely understands what a header is to stuff everything into one header to avoid learning how headers are supposed to be working. That some people who know already how headers work use precompiled headers to speed up compilation is some completely unrelated subject.

##### Share on other sites

Compiler compiles only cpp files . Cpp and h file should be in one file, but the need to have them separate caused for #include directive, so you simply put them to file you need to compile (literaly). The reason to separatet them is, that other projects may need to use your library, but would like to do so without compiling your library, so they just put your h. files to their cpp files and compile them, and on runtime your library internal routine is run. When you will code modules/libraries/projects, whatever is the termine, you will understand also obstacles this design brings.