[C++]How to separate header file and source file.

GOAL

To understand the rules and general method to separate header files and source files in C++.

What is header files?

Header files are files where class definitions and function declarations are summarized. You can use the class written in the header file by writig #include or #include “myheader.h” in source file as follows.

#include <iostream>
#include "myClass.h"
using namespace std;
int main(){
   myClass instance1;
   cout << instance1.getName() << endl;
}

Why are header files necessary?

In C++, variables, classes, functions and so on should be declared before used, like sayHello() or myClass in the sample code below.

//mysource.cpp

#include <string>
#include <iostream>
using namespace std;
void sayHello(){
    cout << "Hello!" << endl;
}
class myClass {
    private:
        string name;
    public:
        myClass();
        myClass(string name_str);
        string getName();
};
myClass::myClass(){
    name = "nothing";
}
myClass::myClass(string name_str){
    name = name_str;
}
string myClass::getName(){
    return name;
}

int main() {
    sayHello();
    myClass cat1("Joe");
    cout << cat1.getName() << endl;
}
//console result
Hello!
Joe

If this declaration is missed or called by wrong name, an error will occur. And when you use the same function or class in multiple files, you have to declare it many times in each file. It is difficult to understand the structured of code if the names of functions that have same function are different. And it is also difficult to make corrections collectively. For this reasons, the declaration part are split into the header files separately from the main source files.

//myClass.h
#include <string>
#include <iostream>

class myClass {
    private:
        std::string name;
    public:
        myClass();
        myClass(std::string name_str);
        std::string getName();
};
myClass::myClass(){
    name = "nothing";
}
myClass::myClass(std::string name_str){
    name = name_str;
}
std::string myClass::getName(){
    return name;
}
//mysource.cpp
#include <iostream>
#include "myClass.h"
using namespace std;
int main() {
    myClass cat1("Joe");
    cout << cat1.getName() << endl;
}
//console result
Joe

About #include

Header files can be loaded with #include or #include “filename”. The difference between the two styles is that when #include is used, the system searches the directory of the library specified by the compiler preferentially, but on the other hand, when #include “filename” is used, the system searches the current directory.

See below for C and C++ standard libraries.

What to put in a header file

Reference: What to put in a header file from Microsoft C++ language reference

In header files, write classes, methods and variable declarations. You can also make class-related definitions.

  • Definitions
    • Class definition
    • Inline function definition
    • Macro definition
  • Declarations
    • extern variable declaration
    • typedef declaration
    • Global function declaration

The declared functions in the header file are defined in the source file. Be aware of items not to be included in the header file. For example, the next chapter explains why variables are only declarated and are’nt defined in the header file.

Items that should not be written in the header file

Reference : What to put in a header file from Microsoft C++ language reference

Items such as duplicate definitions, that may cause confusion.

  • Definition of built-in types (int, float, string, etc.)
  • Anonymous namespace
    • That is definition a class in a namespace that is not named.
  • Using directive
    • If “using” is used, the namespace is also applied indirectly to the source file that read the header file, and it is easy to get confused.

Items that allocate memory area. (When multiple source files are read, each item reserves another area with the same name, which results in duplicate definition.)

  • Non-inline function definition
    • Inline function will be expanded to the call destination, so they have no problem.
  • Defining non-const variables (variables that are not constants)
    • Even if it is static, the variables are not shared and the entity is created for each source file.
    • Use const variables to define constants.

How to define a function?

Write only the declaration in the header file myClass.h.

//myClass.h
void myFunction();

Define the function in one of the .cpp files that are compiled together (either the main source file or myClass.cpp created for each header file).

//myClass.cpp
#include "myClass.h"
void myFunction(){
    printf("This is my function!");
}

In other .cpp files, you can use and use myFuction() defined in myClass.cpp by including only myClass.h.

How to define a variable?

Only “extern” is used in the header file myClass.h.

//myClass.h
extern int myVar;

Define the global variables in one of the .cpp files that are compiled together (either the main source file or myClass.cpp created for each header file).

//myClass.cpp
#include "myClass.h"
int myVar;

In other .cpp files, you can use variables by including only myClass.h. However, it is not recommended because it rarely uses variables in header file and it’s good to use class variables in C++.

Use include guards

Reference: Include guards from Microsoft C++ language reference

Include guard is a mechanism to prevent duplicate inclusion of header files. Duplicate inclusion can occur, for example, if you include one header file A in another header file B, then include A and B from a C++ source file.

//myClass.h
#ifndef MYCLASS_H
#define MYCLASS_H
/*myClass.h本体*/
#endif