MiddleDebuggingCommonNot answered yet
What are the pitfalls of default function arguments in virtual functions and across translation units?
Calling f() through a Base* runs Derived::f, yet the printed argument is 1, not the 2 the author expected. The behaviour surprises every reader.
struct Base {
virtual void f(int x = 1) { std::cout << "Base " << x << '\n'; }
};
struct Derived : Base {
void f(int x = 2) override { std::cout << "Derived " << x << '\n'; }
};
void call(Base* b) { b->f(); } // prints "Derived 1"
Identify the bug and explain the cause.
Defaults bind statically by the static type of the pointer/reference. Base* b = new Derived; b->f(); uses Base's default even though Derived::f runs.
- ✗Overriding a virtual with a different default value — call uses base's default
- ✗Putting different defaults in two headers — ODR violation
- ✗Defaults that depend on globals — non-obvious behaviour at call site
- →Why does the standard pick static binding for default arguments?
- →How does
std::optional/ sentinel value replace default arguments cleanly?