Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Default constructor not inherited with "using" when move and copy constructors present

class A{

public:
    A(){};

};

class B : public A{

public:
    using A::A;

    B(const B&) =   default;
    B(      B&&) =  default;

};

B b;

The compiler (g++ (5.4.0-6ubuntu1) / c++11) says "no matching function for call to B::B()" and lists the copy and move constructors as candidates. If I comment those defaulted ones out then it compiles. What causes this? And what difference does it make that they are explicitly defaulted? If those 2 lines weren't there they would be defaulted anyway.

like image 470
AdyAdy Avatar asked Jun 13 '17 13:06

AdyAdy


People also ask

Is a default constructor 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.

Can copy constructor be inherited?

Copy constructor is not inherited.

Which constructor Cannot be inherited?

Constructors are not members, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass.

Does copy constructor call default constructor?

The answer is No. The creation of the object memory is done via the new instruction. Copy constructor is then in charge of the actual copying (relevant only when it's not a shallow copy, obviously). You can, if you want, explicitly call a different constructor prior to the copy constructor execution.


2 Answers

Before C++17, the default constructor of the base class won't be inherited via using:

All candidate inherited constructors that aren't the default constructor or the copy/move constructor and whose signatures do not match user-defined constructors in the derived class, are implicitly declared in the derived class. (until C++17)

After C++17 the code works fine.

Before that, the default constructor won't be inherited from the base class, and won't be generated for class B because copy/move constructor are provided.

If no user-declared constructors of any kind are provided for a class type (struct, class, or union), the compiler will always declare a default constructor as an inline public member of its class.

That's why if you comment copy/move constructor out it compiles. You can add the definition explicitly as a pre-C++17 workaround. e.g.

class B : public A {
public:
    B(const B&) =   default;
    B(      B&&) =  default;

    B() = default;
};

The code compiles with gcc8.

like image 51
songyuanyao Avatar answered Oct 27 '22 08:10

songyuanyao


If you declare any constructors, the default constructor is not implicitly generated, you can generate it by adding a = default for it as well:

class B : public A {

public:

    B() = default;
    B(const B&) =   default;
    B(      B&&) =  default;
};

This has changed with C++17 (as pointed out by other answer).

like image 45
gauteh Avatar answered Oct 27 '22 10:10

gauteh