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.
In the code shown, byte
and f1()
are being declared multiple times in main.cpp
when file1.h
and file2.h
are both #include
'd.
Per the C++ standard, §8.3.6 [dcl.fct.default]/4:
[Note 2: A default argument cannot be redefined by a later declaration (not even to the same value) ([basic.def.odr]). — end note]
Which is exactly what is happening here.
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.
Making your .h
files have proper header guards (see #pragma once vs include guards?) is the correct and professional way to avoid redeclarations, eg:
file1.h
:
#ifndef File1H
#define File1H
typedef unsigned char byte;
byte f1(byte a, byte b = 5);
#endif
file2.h
:
#ifndef File2H
#define File2H
#include "file1.h"
byte f2(byte a);
#endif