I have a class Property
with a constructor in which I want default parameters, in a file property.h
:
class Property {
Property(OtherClass* value = myApp->someValue) {...};
};
where myApp
, of another type Application
, is defined in another file that makes extensive use of this Property class. Since this other file #includes property.h, of course, I cannot #include this file in property.h
property.h
does not know about myApp
nor Application
(though property.cpp
does, and OtherClass
is known in property.h
).
I could forward declare OtherClass
and declare myApp
as extern
, but this results in an error C2027 "use of undefined type Application", as expected :
class Application;
extern Application* myApp;
class Property {
Property(OtherClass* value = myApp->someValue) {...};
};
A solution could be to have the default parameter in the .cpp file, but this is not advisable (here).
How can I get this default parameter working ? (i.e., not another solution that would involve not having default parameters telling me default parameters are evil, or that my design is poor to start with etc. ;) ). Thanks!
The remarkable point is that the default argument of function parameters is resolved where the function is called (in opposition to where the function is defined). That gives the necessary space to solve OPs problem by yet another level of indirection:
Instead of accessing myApp->someValue
, a helper function is introduced, which can be declared before the definition of Property
but implemented after Application
is fully defined. (This could be a static
member function of Property
as well.)
An example to demonstrate:
#include <iostream>
int getAppDefault();
struct Application;
extern Application *pApp;
struct Property {
int value;
Property(int value = getAppDefault()): value(value) { }
};
struct Application {
int valueDefault = 123;
};
Application app;
Application *pApp = &app;
int getAppDefault() { return pApp->valueDefault; }
int main()
{
Property prop1;
std::cout << "prop1: " << prop1.value << '\n';
app.valueDefault = 234;
Property prop2;
std::cout << "prop2: " << prop2.value << '\n';
}
Output:
prop1: 123
prop2: 234
To emphasize that value = getAppDefault()
is in fact resolved when the constructor Property::Property()
is called, I modified the Application::valueDefault
before default-constructing prop2
.
And, of course, this works as well if the Property
stores a pointer instead of the value itself: