我有一个看起来像这样的类:
class A
{
public:
void foo(int arg) { foo(arg, false); }
private:
void foo(int arg, bool flag) {}
};
它是这样构建的,因为我希望 foo
的标志参数仅在从 A
外部调用时为 false。我想私下继承它,但允许调用 foo
:
class B : private A
{
public:
using A::foo;
};
但是,这失败了,因为 using 声明试图将 foo
的所有重载带入范围,包括编译器正确拒绝的私有(private)重载。
这并不难解决,我可以:
- 将
A::foo(int, bool)
的可访问性更改为 protected 或 public - 公开继承
A
;只有foo
的公共(public)重载将被继承 - 更改
A::foo(int, bool)
的名称,这样 using 声明就不会尝试将其引入范围
这是一个小型私有(private)项目,此外,该重载仅在 A
内部调用。所以解决这个问题在这里不是问题。 (我只是要重命名私有(private)重载。)
但感觉没有必要。为什么 using 声明试图将不可访问的方法引入范围?这种特殊情况是否未包含在标准中?除了我列出的方法之外,还有其他方法可以解决这个问题吗?
最佳答案
您还可以重新定义您想要的重载,并将其参数转发给 A
中的函数:
class B : private A
{
public:
void foo(int arg) { A::foo(arg); }
};
在这种情况下,using 声明是一种过于生硬的工具。它将函数 names 带入派生类范围。当这个名字指的是私有(private)的东西时,它会窒息。它无法区分重载。该标准要求使用 using 声明引入的名称是可访问的:
In a using-declarator that does not name a constructor, all members of the set of introduced declarations shall be accessible. In a using-declarator that names a constructor, no access check is performed. In particular, if a derived class uses a using-declarator to access a member of a base class, the member name shall be accessible. If the name is that of an overloaded member function, then all functions named shall be accessible. The base class members mentioned by a using-declarator shall be visible in the scope of at least one of the direct base classes of the class where the using-declarator is specified.
转发功能也可以模板化。因此不需要重新定义他们想要单独公开的每个函数。
class B : private A
{
public:
template<typename ...Args>
void foo(Args ...args) { A::foo(args...); }
};
它像 using 声明一样是“包罗万象”的,除了访问说明符仅在模板实例化时检查,即在调用函数时检查。因此,根据其范围以及 A
中的成员是否可以在那里访问,模板将是格式错误的。
关于c++ - 对具有私有(private)可访问性的重载继承函数使用声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52158923/