C++ Primer (5th edition) on page 629 states:
- If a base class constructor has default arguments, those arguments are not inherited. Instead, the derived class gets multiple inherited constructors in which each parameter with a default argument is successively omitted.
What is the reasoning behind this rule?
The default constructor in the Person class is not inherited by Employee and therefore a default constructor must be provided in Employee, either automatically by the compiler or coded by the developer.
Constructors are not members, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass.
In inheritance, the derived class inherits all the members(fields, methods) of the base class, but derived class cannot inherit the constructor of the base class because constructors are not the members of the class.
A derived class cannot have a constructor with default parameters. ____ 16. Default arguments can be used with an overloaded operator.
Given the current wording; I think it is specified in these terms (§12.9/1 of C++ WD n4527) for few reasons (but principally to avoid potential ambiguity);
The inheriting constructors is a technique akin to code generation ("I want what my base has"). There is no way to specify which constructors you are getting, you basically get them all hence the compiler much take care to not generate ambiguous constructors.
By way of example;
#include <iostream>
using namespace std;
struct Base {
Base (int a = 0, int b = 1) { cout << "Base" << a << b << endl; }
};
struct Derived : Base {
// This would be ambiguous if the inherited constructor was Derived(int=0,int=1)
Derived(int c) { cout << "Derived" << c << endl; }
using Base::Base;
};
int main()
{
Derived d1(3);
Derived d2(4,5);
}
Outputs;
Base01
Derived3
Base45
Sample code.
There is a proposal out n4429 (as noted by Jonathan Wakely) for a change in the wording around the inheriting constructors and the using declaration for classes.
Given the intent of the proposal;
... this proposal makes inheriting a constructor act just like inheriting any other base class member, to the extent possible.
There is the following change (new wording);
Change in 7.3.3 namespace.udecl paragraph 15:
When a using-declaration brings declarations from a base class into a derived class... Such hidden or overridden declarations are excluded from the set of declarations introduced by the using-declaration.
And immediately follows this with an example that deals directly the constructors (although without default arguments);
struct B1 {
B1(int);
};
struct B2 {
B2(int);
};
struct D1 : B1, B2 {
using B1::B1;
using B2::B2;
};
D1 d1(0); // ill-formed: ambiguous
struct D2 : B1, B2 {
using B1::B1;
using B2::B2;
D2(int); // OK: D2::D2(int) hides B1::B1(int) and B2::B2(int)
};
D2 d2(0); // calls D2::D2(int)
In short, whilst probably not the final wording, it seems that the intent is to allow the constructors to be used with their default arguments and explicitly excludes hidden and overridden declarations thus I believe taking care of any ambiguity. The wording does seem to simplify the standard, yet yielding the same result w.r.t. it being used in client code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With