.h vs. .cpp is a red herring. The rule is that default arguments can be used in function declarations and in the function's definition. You are not allowed to redefine a default argument, not even to the same value. So this is not legal:
void f(int, int = 3);
void f(int, int = 3); // error: redefinition of default argument
However, subsequent declarations can add default arguments:
void f(int, int = 3);
void f(int = 4, int = 3);
f(); // calls f(4, 3);
Further, at any point where the function is called, the default arguments that have been seen at that point can be used:
void f(int, int =3);
f(1); // calls f(1, 3);
void f(int = 4, int = 3);
f(1); // calls f(1, 3);
f(); // calls f(4, 3);
In the original example, the .h file defines one default argument, and any translation unit that uses that header can use that default argument:
Class c3(1, 2, 3);
Class c2(1, 2);
Further, the .cpp file defines an additional default argument, so after that declaration the constructor can be called with one, two, or three arguments:
Class c3(1, 2, 3);
class c2(1, 2);
class c1(1);