测试显示了一种奇怪的行为(c++14
、g++ 4.9.1
、clang 3.5.5
):
综上所述:
- 如果
B
不提供其他构造函数,则可以使用A::A()
- 如果
B
提供了其他构造函数,它就不能使用A::A()
,但它使用了A::A(whatever arguments)
,这是出乎意料的行为(至少对我来说)
设置1:
struct A {
A() {};
A(int) {}; // with or without this overload the result are the same
};
struct B : A {
using A::A;
};
B b0{}; // OK
设置2:
struct A {
A() {}; // with a default constructor instead (empty class A)
// the results are the same
};
struct B : A {
using A::A;
B(int){}
};
B b0{}; // no matching constructor
B b1{24}; // OK
设置3:
struct A {
A() {};
A(int) {};
};
struct B : A {
using A::A;
B(int, int){}
};
B b0{}; // no matching constructor
B b1{24}; // OK
B b2{24, 42}; // OK
为什么会发生这种情况,以及如何"修复"这种情况。
我不能告诉你这样做的理由,但我至少可以告诉你它是标准强制的:
CCD_ 9:对于继承构造函数的候选集合中除了没有参数的构造函数或具有单个参数的复制/移动构造函数之外的每个非模板构造函数,构造函数是用相同的构造函数特性隐式声明的,除非在出现using声明的类中存在具有相同签名的用户声明构造函数[..]
由于默认B()
调用默认A()
,您可以这样"修复"它:
struct B : A
{
B() = default;
using A::A;
B(int, int){}
};
(现场演示)
原始提案(n2540)中的以下措辞表明,这一修复的简单性和对称性或多或少是决定背后的驱动因素,尽管我仍然觉得这有点不令人满意。哦,好吧。
复制构造函数和默认构造函数不被转发,这遵循了隐式声明复制/默认构造函数的现有规则。