对基于访问说明符的特定重载函数使用声明

Using declaration for specific overloaded function based on access specifier

本文关键字:重载 函数 声明 说明符 于访问 访问      更新时间:2023-10-16

此代码

struct Foo{
    void f(){
        f(0);
    }
private:
    void f(int){}
};
struct Bar : private Foo{
    using Foo::f;
};
int main() {
    Bar b;
    b.f();
}

编译失败,因为Foo::f(int) private。我对Foo::f(int)不感兴趣,我只想要Foo::f() public,所以我觉得应该有办法做到。

我能想到一些解决方法:

  1. Foo::f(int)重命名为 Foo::p_f(int) ,但这是多余的,并且不允许f的过载解析
  2. 实现Bar::foo(){Foo::f();}成为多个public f的大量复制/粘贴
  3. 从邀请 UB 的Foo继承 public ly,因为~Foo()不是virtual(也不应该是)
  4. 使所有f public很容易意外破坏FooBar

有没有办法说using public Foo::f;?或者使用其中一种没有相关缺点的解决方法?

如果你的f(int)应该是private的,并且永远不会成为公共API的一部分,那么你不应该关心将其重命名为fimpl

struct Foo{
    void f(){
        fimpl(0);
    }
private:
    void fimpl(int){}
};

另一方面,如果 f(int) 是公共 API 的通用版本,并且您还需要具有特定值的单个便利包装器,则可以使用 提供默认参数并使f(int)成为public成员。

struct Foo{
    void f(int = 0){}
};

最后,如果你想要几个提供某些整数值的命名函数,那么我建议重命名这些包装器

struct Foo{
    void f(int) {} // general interface
    void sensible_name1() { f(0); }
    void sensible_name2() { f(1); } // etc.
}

您的代码当前从Foo派生Bar作为private。因此,Foo::f()Bar中的私有方法。您可以通过将类声明更改为 struct Bar: public Foo 来更改它。

有关一些背景信息,请参阅派生类下的"私有继承"部分。具体而言,本节解释说:

当类使用私有成员访问说明符从基派生时,基类

的所有公共成员和受保护成员都可以作为派生类的私有成员进行访问(除非与好友交朋友,否则永远无法访问基的私有成员)。