The Clang documentation neatly explains that
If a class or struct has no user-defined default constructor, C++ doesn't allow you to default construct a const instance of it like this ([dcl.init], p9)
The following code has such a user-defined default constructor for Base
, but g++ and Clang disagree whether the default constructor for Derived
is user-defined, even though Derived
does explicitly inherit all of the Base
constructors (using the new C++11 inheriting constructors feature)
#include <iostream>
class Base
{
public:
Base(): b_(0) {} // look! user-defined default constructor
void print() const { std::cout << b_ << "\n"; }
private:
int b_;
};
class Derived
:
public Base
{
using Base::Base; // does this constitute a user-defined default constructor?
};
int main()
{
Base const b;
b.print(); // 0 for g++ & CLang
Derived const d;
d.print(); // 0 for g++, Clang: "default initialization of an object of const type 'const Derived' requires a user-provided default constructor"
}
g++ 4.8 happily accepts this code, but Clang 3.3 does not. What does the Standard say?
NOTE: without a user-defined default constructor for Base
, neither g++ 4.8 nor Clang 3.3 accept Base const b;
(whereas e.g. g++ 4.7.2 previously accepted that). Given that g++ knows about the rule, I would think that this implies that g++ regards the default constructor for Derived
as user-defined. But Clang 3.3 thinks otherwise.
UPDATE: based on @JesseGood 's answer that 0/1 argument constructors are never inherited, I tried changing the Base
constructor to
Base(int b = 0, void* = nullptr): b_(b) {}
but it does not resolve the Clang error.
A default constructor is a constructor that either has no parameters, or if it has parameters, all the parameters have default values. If no user-defined constructor exists for a class A and one is needed, the compiler implicitly declares a default parameterless constructor A::A() .
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.
Explanation: The constructors are not always user defined. The construct will be provided implicitly from the compiler if the used doesn't defined any constructor. The implicit constructor makes all the string values null and allocates memory space for each data member.
If you don't define a constructor for a class, a default parameterless constructor is automatically created by the compiler. Default constructor is created only if there are no constructors. If you define any constructor for your class, no default constructor is automatically created.
Clang is correct.
The relevant passage about const instances is from 8.5p7:
If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.
Since Base(): b_(0) {}
is user-provided, Base const b;
is fine.
The next important part is 12.9p3:
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 class where the using-declaration appears
The important part here is the bolded text. I believe this rules out your case since Base()
is a constructor having no parameters. This means that the Derived
does not have a user provided default constructor (although one still is implicitly declared).
What this also means is that default, copy and move constructors from a base class are never inherited.
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