Reputation: 1867
C++ Primer (5th edition) on page 629 states:
I tried this for myself and to me it seems that the derived constructor generated by the compiler also has the same default arguments as the base constructor.
Here's a little test:
#include <iostream>
struct Base
{
Base() = default;
Base(int x_, int y_ = 88, int z_ = 99)
: x(x_), y(y_), z(z_) {}
virtual void debug() const
{ std::cout << "\nx - " << x << ", y - " << y << ", z - " << z << '\n'; }
private:
int x, y, z;
};
struct Derived : Base
{
using Base::Base;
};
int main() {
Base B(1);
B.debug(); // x - 1, y - 88, z - 99
Derived D(5);
D.debug(); // x - 5, y - 88, z - 99
return 0;
}
( You can run this here - http://coliru.stacked-crooked.com/a/26cbb85757c1f021 )
So are we inheriting also the default arguments for a inherited constructor or not?
If not, how come I'm not getting junk for the last 2 members but the same exact values as the default argumuments for the constructor inherited from base?
Also searched on the internet for a clear response about this but found none.
Upvotes: 7
Views: 567
Reputation: 1827
Your quote from the book is not full.
If a base-class constructor has default arguments (§6.5.1, p. 236), those arguments are not inherited. Instead, the derived class gets multiple inherited constructors in which each parameter with a default argument is successively omitted. For example, if the base has a constructor with two parameters, the second of which has a default, the derived class will obtain two constructors: one with both parameters (and no default argument) and a second constructor with a single parameter corresponding to the left-most, non-defaulted parameter in the base class
So your Derived class will have 3 inherited constructors with signatures:
Derived (int x): Base{x} {}
Derived (int x, int y): Base{x, y} {}
Derived (int x, int y, int z): Base{x, y, z} {}
And so you are not inheriting any default arguments from base class.
Derived D(5);
calls the first of above three constructors and base constructor is called like
Base(5)
Also note that the default, copy, and move constructors are not inherited. These constructors are synthesized using the normal rules. An inherited constructor is not treated as a user-defined constructor. Therefore, a class that contains only inherited constructors will have a synthesized default constructor.
Upvotes: 8
Reputation: 303750
From [class.inhctor]:
The candidate set of inherited constructors from the class X named in the using-declaration consists of actual constructors and notional constructors that result from the transformation of defaulted parameters and ellipsis parameter specifications as follows:
— [...]
— for each non-template constructor of X that has at least one parameter with a default argument, the set of constructors that results from omitting any ellipsis parameter specification and successively omitting parameters with a default argument from the end of the parameter-type-list, and
— [...]
We have two non-template constructors of Base
. The default constructor of Base
introduces the candidate:
Derived() : Base() { }
And the other constructor of Base
introduces one candidate for each successively omitted parameter. Namely:
Derived(int x, int y, int z) : Base(x, y, z) { }
Derived(int x, int y) : Base(x, y) { }
Derived(int x) : Base(x) { }
The default arguments are not inherited - we just get a different constructor for each number of arguments. So Derived(5)
simply calls Base(5)
, not Base(5, 88, 99)
.
The end result is the same - just how we get there is a bit different.
Upvotes: 6