Header File Organization

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
Master Jake
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 69
Joined: Sat Dec 12, 2009 8:43 pm
Programming Language of Choice: C/C++
Location: United States
Contact:

Header File Organization

Post by Master Jake »

So, I see these done a lot of different ways and I was wondering if the way I use is proper and elegant.

First off, I have a main header file called Library.h. It includes all the other header files and main files that need to be included. It generally looks something like this.

Code: Select all

#ifndef LIBRARY_H
#define LIBRARY_H

#include "SDL.h"
#include <stdio.h>

#include "Levels.h"
#include "Globals.h"
// etc etc etc

#endif
The Levels.h and Globals.h are just two random files I came up with for the example. They will both generally look like this:

Code: Select all

#ifndef LEVELS_H
#define LEVELS_H

// stuff here

#endif
And the same for globals, except a different define name.

That's generally the structure of my projects.

One other thing I want to ask is about classes. Some people define their class prototypes in a header file and then the classes member functions in a cpp file of the same name, e.g.

Test.h

Code: Select all

class Test
{
	private:
		int lol;

	public:
		Test();
		~Test();

		int WutIsTehLolz();
};
Test.cpp (Edit: accidentally included the prototype in this as well; fixed now)

Code: Select all

Test::Test()
{
	lol = 1;
}

Test::~Test()
{
}

int Test::WutIsTehLolz()
{
	return lol;
}
I just put them all in the same header file, like this:

Test.h

Code: Select all

class Test
{
	private:
		int lol;

	public:
		Test();
		~Test();

		int WutIsTehLolz();
};

Test::Test()
{
	lol = 1;
}

Test::~Test()
{
}

int Test::WutIsTehLolz()
{
	return lol;
}
Does it matter which you use, and is my above structure the "right" way to do it?
vargonian
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 60
Joined: Fri Aug 07, 2009 3:34 pm

Re: Header File Organization

Post by vargonian »

This is just one of the many reasons why I'm so glad I use C# now. None of these annoying issues even matter anymore. /extraneous commentary

A couple things, based on my rusty memory of C++:

If you're using a modern compiler, you shouldn't need to use the #ifndef/#define/#endif guards everywhere. You can simply write #pragma once at the top of your header file and it will handle that for you.

Second, from my experience it is almost always preferred to separate your interface from your implementation in C++. In other words, yes, you should have just the declarations in the .h file, and the implementations in the .cpp file. I can't give you the super expert programmer's reason why this is, but from a practical standpoint, you will run in to much fewer hellish dependency issues. (Actually, I would say that including implementation in a header file is less of a crime than including interface code in a .cpp file, now that I think of it.)

I'm actually struggling now to think of specific examples of problems that arise by including everything in the header. But whenever possible you should be able to use forward declarations of classes (i.e. class MyClass;) instead of #include MyClass.h, and with the pattern you're describing, it seems like you'd necessarily have #includes everywhere. This is a recipe for introducing circular dependencies.

I'm sorry for my mediocre explanation; I'm sure someone on this forum knows better than I do.
Image
Master Jake
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 69
Joined: Sat Dec 12, 2009 8:43 pm
Programming Language of Choice: C/C++
Location: United States
Contact:

Re: Header File Organization

Post by Master Jake »

Well, what I try to do is make sure that each file is only included once (I'll try that pragma thing, I've never used that pre-processor command before).

Each file is included once into the library file, and then the library file is included once into Main. The only thing I've had to worry about doing this (so far) is that if one of my header files uses datatypes from another header file, the one being used must be included in the library.h file first.

Example:

Test.h

Code: Select all

class Test
{
	private:
		Extender ext;

	public:
		// blah blah blah
};
Extender.h

Code: Select all

class Extender
{
	// blah blah blah
};
In that case, Test uses Extender, so in the library file, it would have to be in this order:

Code: Select all

#include "Extender.h"
#include "Test.h"
Which would become a problem if those 2 header files used EACHOTHER. I know that this is what prototypes are for.

e.g. defining a function like this:

void Function(parameters);

so that you can use it later without having to worry about the order.

But, for some reason, when I made class prototypes (e.g. class MyClass;) it didn't work.
User avatar
MarauderIIC
Respected Programmer
Respected Programmer
Posts: 3406
Joined: Sat Jul 10, 2004 3:05 pm
Location: Maryland, USA

Re: Header File Organization

Post by MarauderIIC »

You generally only want to include what you need when you need it, if for no other reason than it speeds your compilation time up a bit. (It also makes maintenance easier, as you can see what is needed for a particular class to work). So an include that has all your includes is a "bad idea".

In header files, use class prototypes when you can. You can't use a class prototype if you have a class that contains an instance of a class (as opposed to a pointer or reference to a class object), IIRC.

IE:

Code: Select all

class B;
class A {
    B* b;
};

Code: Select all

class A;
class B {
    A* a;
};
Would work, but

Code: Select all

class B;
class A {
    B b;
};
would not. In this case, you would have to do

Code: Select all

#include "B.h"
class A {
    B b;
};
... I think. It's been a while since I've had to deal with circular dependencies.
I realized the moment I fell into the fissure that the book would not be destroyed as I had planned.
User avatar
dandymcgee
ES Beta Backer
ES Beta Backer
Posts: 4709
Joined: Tue Apr 29, 2008 3:24 pm
Current Project: https://github.com/dbechrd/RicoTech
Favorite Gaming Platforms: NES, Sega Genesis, PS2, PC
Programming Language of Choice: C
Location: San Francisco
Contact:

Re: Header File Organization

Post by dandymcgee »

MarauderIIC wrote: In this case, you would have to do

Code: Select all

#include "B.h"
class A {
    B b;
};
... I think. It's been a while since I've had to deal with circular dependencies.
Yup. If there's ever a case where you can't define a class before it's used (circular dependency) you must, at the very least, declare it.
Falco Girgis wrote:It is imperative that I can broadcast my narcissistic commit strings to the Twitter! Tweet Tweet, bitches! :twisted:
Master Jake
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 69
Joined: Sat Dec 12, 2009 8:43 pm
Programming Language of Choice: C/C++
Location: United States
Contact:

Re: Header File Organization

Post by Master Jake »

Thanks, MarauderIIC. =)
User avatar
MarauderIIC
Respected Programmer
Respected Programmer
Posts: 3406
Joined: Sat Jul 10, 2004 3:05 pm
Location: Maryland, USA

Re: Header File Organization

Post by MarauderIIC »

Also, #pragma once doesn't seem to always work correctly, in my experience with MSVS compilers. #ifndef #define #endif always works.
I realized the moment I fell into the fissure that the book would not be destroyed as I had planned.
Live-Dimension
Chaos Rift Junior
Chaos Rift Junior
Posts: 345
Joined: Tue Jan 12, 2010 7:23 pm
Favorite Gaming Platforms: PC - Windows 7
Programming Language of Choice: c++;haxe
Contact:

Re: Header File Organization

Post by Live-Dimension »

MarauderIIC wrote:Also, #pragma once doesn't seem to always work correctly, in my experience with MSVS compilers. #ifndef #define #endif always works.
Some compilers won't support it as it's not a proper c++ standard.
*always* use #ifndef #define #endif if only for portability. It's not that difficult to do, really.

edit: At worst, if you find yourself having difficulty making up lots of different #define statements (ie three different sprite.h's) you could either do folder structure ( #define graphics_objects_sprite) or make a small random-generating 12-24 character generator and use those (#define sy48sl26dn48s) would do the same job, in my limited experience anyway.
Image
User avatar
eatcomics
ES Beta Backer
ES Beta Backer
Posts: 2528
Joined: Sat Mar 08, 2008 7:52 pm
Location: Illinois

Re: Header File Organization

Post by eatcomics »

I've always had troubles with #pragma

and I'm glad MasterJake brought this up (keep up the videos jakey) because I've been trying to split up my SDL platformer and I keep getting circle dependencies. On top of that I was using a Library.h header too :lol:

So thanks for the help guys :D
Image
Post Reply