在没有朋友的情况下向私有构造函数授予访问权限

Grant access to private constructor without friends?

本文关键字:访问 访问权 权限 构造函数 朋友 情况下      更新时间:2023-10-16

我正在处理一些代码,其中遇到了与此类似的情况:

struct Bar;
struct Foo{
    friend struct Bar;
private:
    Foo(){}
    void f(){}
    void g(){}
};
struct Bar {
   Foo* f;
   Bar()  { f = new Foo();}
   ~Bar() { delete f;}
};
int main(){
  Bar b;
}

我宁愿Bar不像Foo那样friend,因为除了Foo的构造函数之外,Bar不需要访问Foo的任何私有方法(因此不应该有访问权限(。有没有办法只允许Bar创建Foo而不让他们成为朋友?

PS:意识到这个问题可能不是100%清楚的。我不介意是否通过朋友,只是所有Bar都可以访问所有私人方法这一事实让我感到不安(friends通常是这种情况(,这就是我想避免的。幸运的是,到目前为止给出的答案都没有对这种糟糕的表述有问题。

这正是律师-客户习语的用途:

struct Bar;
struct Foo {
    friend struct FooAttorney;
private:
    Foo(){}
    void f(){}
    void g(){}
};
class FooAttorney {
  static Foo* makeFoo() { return new Foo; }
  friend struct Bar;
};
struct Bar {
   Foo* f;
   Bar()  { f = FooAttorney::makeFoo();}
   ~Bar() { delete f;}
};
int main(){
  Bar b;
}

在模仿生活时尚的代码中,班级声明一名律师将调解它愿意与选定各方分享的秘密。

如果你不想介绍另一个类,你可以缩小友谊圈,让Bar的构造函数Foo的朋友。它要求Bar的定义可供Foo使用,并且它仍然允许Bar的构造函数不受限制地访问Foo的私有实现:

struct Foo;
struct Bar {
   Foo* f;
   Bar();
   ~Bar();
};
struct Foo{
    friend Bar::Bar();
private:
    Foo(){}
    void f(){}
    void g(){}
};
Bar::Bar() : f(new Foo()) {
}
Bar::~Bar() {
    delete f;
}

这并没有达到你想要的,但它使友谊更有针对性。

我想到的一种方法是有一个内部class,使Bar成为它的朋友,这样只有Bar才能创建它,并且内部class可以用作构造函数Foo附加参数,这样只有class的朋友才能调用它。

class Foo
{
public:
    // only friends of the special key can invoke the constructor
    // or any member function that includes it as a dummy parameter
    class special_key {friend class Bar; special_key(){}};
    // making special_key a dummy parameter makes sure only friends of
    // the special key can invoke the function
    Foo(special_key) {}
    void f(){}
    void g(){}
};
class Bar
{
public:
    // only Bar functions can create the special key
    Bar() { f = std::make_unique<Foo>(Foo::special_key()); }
private:
    std::unique_ptr<Foo> f;
};

除了限制对特定功能的访问外,该技术还允许使用直接友谊所没有的智能指针make函数。