Copy constructor is not inherited
Because the standard says so. [class.inhctor]/p3, emphasis mine:
For each non-template constructor in the candidate set of inherited constructors other than a constructor having no parameters or a copy/move constructor having a single parameter, a constructor is implicitly declared with the same constructor characteristics unless there is a user-declared constructor with the same signature in the complete class where the using-declaration appears or the constructor would be a default, copy, or move constructor for that class.
Derived class should inherit all ctors of base except the default ctor
No, that's not true, see T.C.'s answer for the real rule.
The purpose of inheriting constructors is to say "the derived type can be created from the same arguments as the base type", but that isn't relevant for the base class' copy constructor, because a copy constructor is not just a way of saying how to create a type from a given argument.
A copy constructor is special, it's for copying an object of the same type.
A constructor D(const C&)
would not used be for copying an object of the same type, because C
is not the same type as D
.
For a moment, we’ll assume ‘copy constructor inheritance’ is allowed. Having your class structure intact, please consider following code for modified main method.
int main() {
C c;
D d;
D d_from_d(d);
D d_from_c(c); // does not compile, copy ctor is not inherited
D d_from_int(1); // compiles, C(int) is inherited
}
In D d_from_d(d)
, as a normal constructor call, there will be two copy constructor calls. One for C::C(const C&) and the other one is for compiler generated copy constructor for D. Having source object type in D (d in this case), C’s copy constructor can copy d’s C attributes while compiler generated D’s copy constructor can copy d’s D attribute.
But in D d_from_c(c)
case, There is no problem for C’s copy constructor because, c’s C attributes can be copies by C’s copy constructor. But how does the compiler generated D’s copy constructor know the way to copy ‘D’s attributes from C’s object’. This is a conflict which should be avoided.
But, if you provide some sort of ‘weird copy constructor’ (you may need to a default constructor as well) like;
D(const C & c):C(c){}
Then,
calling D d_from_c(c);
is valid. Because, now we have explicitly provided a matching ‘copy’ constructor.
So, saying ‘Inheriting copy constructors are now allowed’ is invalid.