views:

3245

answers:

6

Hi, I am new to C++ and I had a few general questions about code separation. I have currently built a small application, all in one file. What I want to do now is covert this into separate files such that they contain similar code or whatnot. My real question right now is, how do I know how to separate things? What is the invisible margin that code should be separated at?

Also, what's the point of header files? Is it to forward declare methods and classes so I can use them in my code before they are included by the linker during compilation?

Any insight into methods or best practises would be great, thanks!

+9  A: 

Header files should contain class and function declarations.

Source files contain class and function definitions.

It is standard practice (i.e. read easier) to have one declaration per header file and one definition per source file, though for small (read simpler helper) objects you sometimes group them with related more substantial objects.

Example: Class Menu

Menu.h:     Contains the Menu declaration.
Menu.cpp:   Contains the Menu definition.

The reason header files contain the declarations is so that you can include them from multiple source files and thus each source file has exactly the same definition of each class and function.

Consider it this way:
If you did not have header files then you would need to have the class and/or function declarations (without) definitions in every source file, this means a copy of the same declaration in every file. Thus if you modify a class you need to make the same modification in every file. By the use of a header file you have the declaration in one place and thus only one object to modify.

Martin York
Note that struct Menu { int bar; void foo(); }; is a *definition* of class Menu, but a *declaration* of member function foo, but a *definition* of object member bar. your answer sounds like it was a declaration of class Menu
Johannes Schaub - litb
Also that header files often do contain function definitions. For instance: "small" member functions intended to be inlined; free functions declared "static inline"; function templates.
Steve Jessop
This is a beginners course on how to spit code between the appropriate files.
Martin York
In that case I'll let you off the function definitions, but even a beginner's course should be clear on the difference between a class declaration and a class definition, and that header files frequently contain class definitions.
Steve Jessop
+3  A: 

Deciding how to separate your code into different classes/functions is one of main tasks of programing. There are many different guidelines on how to do this and I would recommend reading some tutorials on C++ and Object Oriented Design to get you started.

Some basic guidelines will be

  • Put things together which are used together
  • Create classes for domain objects (eg files, collections etc)

Header files allow you to declare a class or function and then use it in several different source files. For example, if you declare a class in a header file

// A.h
class A
{
public:
    int fn();
};

You can then use this class in several source files:

// A.cpp
#include "A.h"
int A::fn() {//implementation of fn}

//B.cpp
#include "A.h"
void OtherFunction() {
    A a;
    a.fn();
}

So header files enable you to separate the declaration from the implementation. If you were to put everything (declaration and implementation) in a source file (eg A.cpp) then try to include that in a second file, eg

// B.cpp
#include  "A.cpp" //DON'T do this!

Then you could compile B.cpp but when you try to link your program the linker will complain that you have multiply defined objects - this is because you have multiple copies of the implementation of A.

David Dibben
+4  A: 

Programming Techniques:C/CPP Header File Convention
Organizing Code Files in C and C++

Dustin Getz
Great resources, looks like a good read, thanks!
+5  A: 

First, you should not put anything into headers that is not needed to be visible by any other file, other than the one that needs it. Then, let's define something we need below.

Translation Unit

A Translation Unit is the current code being compiled, and all the code included by it, directly or indirectly. One Translation unit translates to one .o / .obj file.

Program

That's all your .o / .obj files linked together into one binary file that can be executed to form a process.

What are the main points of having different translation units?

  1. Reduce dependencies, so that if you change one method of one class, you don't have to recompile all the code of your program, but only the affected translation unit. An
  2. Reduce possible name clashes by having translation unit local names, that are not visible by other translation unit when linking them together.

Now, how can you split your code into different translation units? The answer is there is no "so you do it!", but you have to consider it on a case-by-case basis. It's often clear, since you have different classes, which can and should be put in different translation units:

foo.hpp:

/* Only declaration of class foo we define below. Note that a declaration
 * is not a definition. But a definition is always also a declaration */
class foo;

/* definition of a class foo. the same class definition can appear 
   in multiple translation units provided that each definition is the same  
   basicially, but only once per translation unit. This too is called the  
   "One Definition Rule" (ODR). */
class foo {
    /* declaration of a member function doit */
    void doit();

    /* definition of an data-member age */
    int age;
};

Declare some free functions and objects:

/* if you have translation unit non-local (with so-called extern linkage)  
   names, you declare them here, so other translation units can include  
   your file "foo.hpp" and use them. */
void getTheAnswer();

/* to avoid that the following is a definition of a object, you put "extern"  
   in front of it. */
extern int answerCheat;

foo.cpp:

/* include the header of it */
#include "foo.hpp"

/* definition of the member function doit */
void foo::doit() {
    /* ... */
}

/* definition of a translation unit local name. preferred way in c++. */
namespace {
    void help() {
        /* ... */
    }
}

void getTheAnswer() {
    /* let's call our helper function */
    help();
    /* ... */
}

/* define answerCheat. non-const objects are translation unit nonlocal  
   by default */
int answerCheat = 42;

bar.hpp:

/* so, this is the same as above, just with other classes/files... */
class bar {
public:
    bar(); /* constructor */
};

bar.cpp:

/* we need the foo.hpp file, which declares getTheAnswer() */
#include "foo.hpp"
#include "bar.hpp"

bar::bar() {
    /* make use of getTheAnswer() */
    getTheAnswer();
}

Please note that names within an anonymous namespace (as above) do not clash since they appear to be translation unit local. in reality they are not, they just have unique names so that they do not clash. if you really want (there is little reason to) translation unit local names (for example because of compatibility with c so C code can call your function) you can do it like this:

static void help() { 
    /* .... */
}

The ODR also says that you cannot have more than one definition of any object or non-inline function in one program (classes are types, not objects, so it doesn't apply to them). So you have to watch out not to put non-inline functions into headers, or not putting objects like "int foo;" in headers. That will cause linker errors then when the linker tries to link the translation units including those headers together.

I hope i could help you a bit. Now that was a long answer, there are indeed errors somewhere. I know that a translation unit strictly is defined another way (output of the pre-processor). But i think it would not add big value to include that into the above, and it would confuse the matter. Please feel free to slap me if you find real bugs :)

Johannes Schaub - litb
A: 

I had a project for which I created a tool to build executables based on an XML-file that specifies the features for the executables. In VS2009 headers and implementation were both organized in separate folders. I tried to create a new project with my source files, but now it doesn't show them separated and doesn't compile.

Any suggestions on how to get this separation back in VS2008?

You'll probably want to submit this as a question and not an answer to somebody else's question.
Max Lybbert
A: 

Suggestion: 1. Have a design ready for your application now. 2. Based on the design, create necessary objects that interact with each other. 3. Refactor or completely change the existing code to suit the newly created design.

Header files provide an interface to the other classes that might use it's functionality.

Elroy