Only using headers?

Pages: 12
I've been messing with C++ for over a year now, And I've only used a single file for my projects.
I plan on making quite a large and long term project, and modability from other people is one of my goals during the creation of it, So I figured i'd start using multiple files for easier management.

After taking awhile to get some things to work in multiple files from one, I could only get it to work if I had the whole code in the .h file, instead of a .cpp, otherwise getting a multiple definition error.

I have a simple question here, Is there any reason I should use .cpp files over .h files?

I simply cannot get most functions to work in other files unless they are in the header only, Maybe I'm missing a keypoint here.
closed account (3TXyhbRD)
Hello,

You are missing a something. The reason of having both .h and .cpp files is to hide the implementation and make public only the interface. Specify your function prototypes, classes etc. in .h files and implement them in a .cpp file. Here's a 3 file example:

Useful.h file
1
2
3
4
5
6
7
#ifndef USEFUL_H
#define USEFUL_H

// Adds two numbers and returns the result.
int add(int a, int b);

#endif 


Useful.cpp file
1
2
3
4
5
6
#include "Useful.h"

int add(int a, int b)
{
	return a + b;
}


main.cpp file
1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include "Useful.h"

using namespace std;

int main()
{
	cout<<add(1, 2)<<endl;
	return 0;
}
Last edited on
I understand that part, However, I need to use a bool from Input.h, in both Main.cpp, and Useful.cpp, And when I include input in both of those files, I get multiple declaration errors, But when I include input.h in Useful.h, and run the stuff I need to in Useful.h, It works fine.

So I'm assuming a .cpp is like Private in a class, and .h is Public?
Everybody develops their own style, as needed, and what LilJoe posted is 100% valid and applicable for C-style programming; but for C++ OOP, I personally prefer the Java-esque approach of defining class member functions inside hpp files, inside the class they're part of.

The verbosity is slightly diminished, and on the other hand you will have to do things this way for template classes (for technical reasons: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12 ).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef PERSON_HPP
#define PERSON_HPP

class Person {
private:
    int age;

public:
    Person() {}
    // ...
    void show_age()
    {
        std::cout << age;
    }
    // etc.
};

#endif 
Putting all the code in header files have a few shortcomings.
* You are forced to declare the functions as inline or use templates.
* Circular dependencies between classes is much harder (impossible?).
* You can't define static variables with external linkage in header files.
... there are probably more problems that I can't think of know.
Last edited on
I understand that part, However, I need to use a bool from Input.h, in both Main.cpp, and Useful.cpp, And when I include input in both of those files, I get multiple declaration errors, But when I include input.h in Useful.h, and run the stuff I need to in Useful.h, It works fine.


That bool variable is a global, and the problem is that you're defining it multiple times (this is an artifact caused by including its definition multiple times).

The solution is this: put it in a file globals.cpp, then create a regular header file globals.h where you only declare the globals variables, by using extern.

1
2
3
4
5
6
7
8
#ifndef GLOBALS_H
#define GLOBALS_H

extern bool var1;
extern int var2;
// etc.

#endif 
Tried using _HPP, I get multiple declarations when using it, Trying "extern" now, Does that work for functions and classes as well?
The extension of a file doesn't matter.
The name of the macros used as header guards doesn't matter.

Does that work for functions and classes as well?

It's not needed.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int a; // definition
extern int a; // declaration (can be repeated)

void f(int i) // definition
{
}

void f(int i); // declaration (can be repeated)

class C // definition
{
}

class C; // "forward declaration" (can be repeated) 

A problem with Forward declaring classes I've noticed, It doesn't appear to remember it's inherited variables, And Extern appears to be helping.
Another one, you will need to recompile all the project if you modify the implementation of a function.

@OP: please provide an example.
Also, global variables are evil ┬┐couldn't just pass it as parameter?
Last edited on
Strange, extern doesn't seem to prevent multiple definitions.

What do you mean pass it as a parameter?

Also, I'm great with naming variables, So globals are not a problem for me, So long as the common problem is accidentally overwritting it, I've yet to see any other possible problem with them.

And these files are a pain to include other globals, So it's nearly impossible for me to accidentally tread old ground.
Last edited on
Strange, extern doesn't seem to prevent multiple definitions.


I'd like to see the contents of the header file that gives errors.
1
2
3
4
5
6
7
8
9

#ifndef KEYS_H
#define KEYS_H

extern bool plat = true;

#endif 



Simple as that, If I include Keys.h in more than one .cpp file, I get multiple declaration errors, weird ones though, after it builds, it says the file didn't exist, than asks to rebuild again, after that, I get the multiple declaration errors.

Also, Oddly enough, I think extern is working for a function declaration I have in a .h for multple files.

Nevermind, I forgot to re-enable the .h.

Alright, Figured out the Extern for variables, Although through all this it still appears I'd have to use .h's for my functions.

Gotta admit, Things were alot simpler when using one file.

Thanks for the help, I'll be continuing to fiddle with the new data ya'll have given me.
Last edited on
I would expect just this in the header

1
2
3
4
5
6
7
8
// keys.h

#ifndef KEYS_H
#define KEYS_H

extern bool plat;

#endif 


And then the following in one of the cpp filea

1
2
3
4
5
6
7
8
9
10
11
// somefile.cpp

// etc...

#include "keys.h"

// etc...

bool plat = true;

// etc... 
Last edited on
The multiple definition thing is due to you giving the variable multiple "bodies". It's easier to visualize with functions, so let me use that as an analogy.

If you put a function body in a header file and #include that header file in two separate cpp files, you will get the same error. The reason for this is because each cpp file is compiled individually, then the compiled function bodies are "linked" together to form the final executable. If the same function has bodies in two different cpp files, then the linker gets confused because it sees two cpp files giving a body for the same function and it doesn't know which one to use.

To get around the issue, you declare a "prototype" in the header, then define the "body" in only one cpp file.

1
2
3
//myfunction.h

int myfunction();  // the prototype 

1
2
3
4
5
6
7
//myfunction.cpp
#include "myfunction.h"

int myfunction()  // the function body
{
  // do some stuff here
}



Global variables are the same way. When you make a global variable, you are telling the compiler to reserve some memory for that variable. The linker then combines all those variables together in the final executable. But if two different cpp files are giving it two different variables to use with the same name, it gets confused.

In this sense, the "extern" keyword is a lot like a prototype. It tells the compiler that the variable exists somewhere, but doesn't actually create it. It's assumed that the linker will "fill in" the body after all the cpp files have been compiled.

1
2
3
// myglobal.h

extern int myglobal; // the variable "prototype" 

1
2
3
4
// myglobal.cpp
#include "myglobal.h"

int myglobal = 0; // the variable "body" 



EDIT:


That said... global variables are ATROCIOUS and you should really avoid using them. They severely cripple your code and make program management and maintenance much more difficult. They may seem simpler for small program, but as your program gets larger, they will make things more and more unwieldly.


They also get you in the practice of writing crappy code that is not reusable. When your code works with a global... it ONLY works with that global. When your code works with parameters, it can work with ANYTHING, making it much more functional and much more reusable.


Here's a classic example. Let's say you're writing a simple game and have a player fighting a goblin. You decide to have player and goblin life/hp stored as global variables.

Then you write a function to damage the player:

1
2
3
4
5
6
7
8
9
int playerhp = 100;
int goblinhp = 20;

// hurts the player, returns true if the player is still alive, false if the player is dead
bool HurtPlayer( int damage )
{
  playerhp -= damage;
  return (playerhp > 0);
}


Seems fine, right?

The problem is... that function only works with the player. Say you want to do the same thing with the goblin. You now have to write an entirely separate function:

1
2
3
4
5
6
// likely just a copy/paste of HurtPlayer
bool HurtGoblin( int damage )
{
  goblinhp -= damage;
  return (goblinhp > 0);
}


Now what happens when you want to add more enemies? Or more players? Do you copy/paste this function for all of them? What if you want to change how these functions work (to add some kind of defense calculation or something). Do you go back and change each and every one of the dozen identical functions?


Because you used globals, the functions can only be used with those globals. It makes them extremely restrictive.


Compare that to a function that uses no globals:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
bool DamageObject( int& objecthp, int damage )
{
  objecthp -= damage;
  return (objecthp > 0);
}

//...

int main()
{
  // to damage the goblin
  DamageObject( goblinhp, 5 );

  // to damage the player
  DamageObject( playerhp, 4 );

  // etc 





And that's just one example of why globals are horrible. There are many more.
Last edited on
@Andy, Yeah figured that out almost the same time you posted that, Barely beat you there, hehe.

@Disch, Did you include myfunction.h 'inside' myfunction.cpp?

And my main problem, Is I'm trying to use bools from one.h, both in main.cpp, and two.cpp, However I believe I know how to fix that now with extern,
Actually, Maybe not.
A big problem I'm having, is I can only set the variables for one.h/.cpp, using main.cpp, Can I access one.cpp from main?

Also, How do you use a Class Vector from Main.cpp, in another file?

Edit:

Whoa, You may have finally gotten my head to wrap around references, Anyways I usually deal with that stuff using Class Vectors, everything defrives from an "Entity" class, and those classes only have variable fillers inside them, so I can simple do everything by checking names or variables, taking account of defence points, strengths, ect.

I still haven't figured out how to properly use pointers in a large system.
Last edited on
@Disch, Did you include myfunction.h 'inside' myfunction.cpp?


Yes. myfunction.h should be included in all files that use any functions it declares.

And my main problem, Is I'm trying to use bools from one.h, both in main.cpp, and two.cpp, However I believe I know how to fix that now with extern,
Actually, Maybe not.


I'd argue that your main problem is one of design, and you should not be trying to use global variables at all. But if you want to use them, my previous post shows you how.

Can I access one.cpp from main?


That depends on what you mean by "access".

You can call functions in x.cpp from y.cpp as long as the function prototypes have been declared in the y.cpp. This is usually done by #including a header file that has all the prototypes.

ie:
header.h declares the prototypes
x.cpp defines the function bodies
y.cpp includes header.h for the prototypes, then can call the functions

Global variables work the same way, but replace "prototype" with "extern declaration" and "function body" with "non-extern declaration".... but again... avoid globals.



Also, How do you use a Class Vector from Main.cpp, in another file?


Quickest way is to pass it as a parameter.



-------EDIT-----------

Anyways I usually deal with that stuff using Class Vectors, everything defrives from an "Entity" class, and those classes only have variable fillers inside them, so I can simple do everything by checking names or variables, taking account of defence points, strengths, ect.


If you're already using classes, that's great. I would have brought that up as an example in my previous post but I didn't want to overwhelm you too much as it's sort of a side topic.


So if all of your stuff is in a class like it should be... what do you need the globals for?
Last edited on
I must have missed something large awhile back, What do ya'll mean by "Parameter"?

Edit:
And would it make it better if I put all my global variables inside a class? I've thought of doing that, but it seemed like the same thing, only possibly causing more problems later on.

Edit: Hah, ^

Edit: About the accessing, We include one.h into main.cpp, But not one.cpp, which is where the variable is actually kept, Although I've yet to try including the header inside of the actual cpp, so maybe that allows for it.
Last edited on
I must have missed something large awhile back, What do ya'll mean by "Parameter"?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void function( int parameter )
{
  // 'parameter' is a parameter
  //  it's basically a variable that is passed to the function
}

int main()
{
  function( 5 );  // calls 'function' with parameter=5

  function( 15 ); // calls function with parameter=15

  int foobar = 1;
  function( foobar );  // calls function with parameter=foobar (1)
}


And would it make it better if I put all my global variables inside a class?


Not necessarily. Variables should go with their owner. Who their owner is depends on how they are used.

Tell me what variables you have now that are global and I'll try and advise where they would best be owned.
The global variables... whew, Theres tons, Everything from grid declaration, to mathmatical equation constants(Like Pi) although those are never changed, being constants.

Actually, reading over it, I don't have that many non constant globals, and the ones I do have, are only used by one or two functions, The main reason I use globals at all, is so more than one function can read it. Only one or two things actually edit it, and they go through a single function to do so to keep the variable correct, And I didn't realize that was a parameter.



1
2
3
4
5
class entity{all variables and functions}
class human : public entity{}
class NPC : public human{}

std::vector<NPC> npclist; (Which is full of many different types of npc's, all the same structure, just different variables. 


which is in main.cpp
How would I access npclist, from one.h?
Does it have to do with Referencing? (&)
Last edited on
Pages: 12