Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is an inherited default constructor also user-defined?

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.

like image 801
TemplateRex Avatar asked May 27 '13 21:05

TemplateRex


People also ask

Is default constructor user defined?

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() .

Are default constructors inherited?

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.

Are constructors always user defined?

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.

What is difference between default and user defined constructor?

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.


Video Answer


1 Answers

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.

like image 165
Jesse Good Avatar answered Sep 21 '22 16:09

Jesse Good