在父类中公开受保护的构造函数

Exposing protected constructor in parent class

本文关键字:受保护 构造函数 父类      更新时间:2023-10-16

正如标题所说,我想知道是否有办法在派生类中公开受保护的构造函数(即将访问权限从protected更改为public(。考虑以下(人为的(示例:

struct A {
int a;
int b;
protected:
A(int, int) {};
void do_something();
};
struct B : A {
B() : A(0, 0) {};
using A::A;
using A::do_something;
};
int main() {
B b(0, 0); // error: 'A::A(int, int)' is protected
//B b{}; // no errors
b.do_something();
}

因此,可以更改受保护成员函数的访问,但不能更改构造函数的访问?如果是这样,限制的理由是什么?

解决办法

:具有参数转发的可变参数模板可以用作执行相同的解决办法。


对基本原理的推测:默认情况下,基类的构造函数不是常规意义上的"继承";派生类的构造函数必须首先构造基类实例。当using用于常规成员函数时,它将函数引入当前声明性区域,从而更改访问;在构造函数上,using仅将基构造函数带到"正常继承"级别(与其他成员函数相同,没有using(。因为只有在某些情况下构造函数继承(重用基构造函数(才有用,所以标准委员会的人指定using X::X构造函数继承的语法,而不是更强的命名空间传送。

您要做的是使用两个参数调用构造函数 B,但它不需要任何参数。

你得到的错误是关于 B 的构造函数受到保护,但如果你仔细观察,这不是你声明的构造函数:

error: 'B::B(int, int)' is protected

为什么? 因为编译器正在尝试解析对有效内容的调用,并且它会找到与签名匹配的基类构造函数。但它仍然受到保护,因此会失败。

要将受保护的构造函数"重新启动"到继承的类,您需要做的是提供一个匹配的构造函数:

struct B : A {
B() : A(0, 0) {};
B(int a, int b) : A(a, b) {};
using A::A;
using A::do_something;
};
int main() {
B b;
B b2(1, 2);
//b.do_something();
}

http://cpp.sh/9tvik

您不能像更改方法一样更改构造函数的访问器级别,其原因很可能是搜索构造函数的非虚拟性质。[需要引用:)]