I am trying to build a small program in C++, to learn the preprocessor directives and how they actually work.
The program is made up of 5 files: main.cpp, file1.h, file1.cpp, file2.h and file2.cpp
In file1.h, I declared 1 function that has the default parameter, and a new type byte:
typedef unsigned char byte;
byte f1(byte a, byte b = 5);
In file1.cpp, I defined it:
#include "file1.h"
byte f1(byte a, byte b) {
    return a + b;
}
In file2.h, I declared a second function that uses f1(), and always passes 10 to it as a second argument:
#include "file1.h"
byte f2(byte a);
And the same, in file2.cpp, I defined it:
#include "file2.h"
byte f2(byte a) {
    return f1(a, 10);
}
And finally, here is the main file:
#include <iostream>
using namespace std;
#include "file1.h"
int main() {
    cout << f1(3) << endl;
    return 0;
}
For now, all is Ok, and the output is simply 8.
But suppose I need to use the f2() function in my main file, and for that I included
the file2.h, so the main file is now:
#include <iostream>
using namespace std;
#include "file1.h"
#include "file2.h"
int main() {
    cout << (int) f1(3) << endl;
    cout << (int) f2(2) << endl;
    return 0;
}
The compiler is giving this error: Error   C2572   'f1': redefinition of default argument: parameter 1
Since file1.h is included in file2.h, now f1() is redeclared in file2.h with the b paramter also set to 5.
What can I do to prevent the redefinition, if we assume that I can not move the f2() declaration and definition to file1.h and file1.cpp respectively?
Note: I know that I could use #pragma once directive, but I am trying to solve this problem without it, since I am trying to learn the C++ directives professionally.