问题
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.
回答1:
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.
回答2:
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).
回答3:
The default constructor cannot be inherited, the standard explicitly says so. Quoting C++11 12.9 [class.inhctor]/3 (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 class where the using-declaration appears. ...
This means that for the default constructor, normal rules apply as if the using A::A;
declaration wasn't there. So the presence of any other constructor declaration (such as the copy & move constructor) causes the default constructor not to be implicitly declared. Note that you can easily add it back by explicitly defaulting it:
class B : public A{
public:
using A::A;
B() = default;
B(const B&) = default;
B( B&&) = default;
};
(*) The same wording is present in C++14 (n4140), at the same location. I can't seem to find equivalent wording in C++1z (looking through n4582)
来源:https://stackoverflow.com/questions/44522331/c-default-constructor-not-inherited-with-using-when-move-and-copy-constructo