【问题标题】:Grant access to private constructor without friends?在没有朋友的情况下授予对私有构造函数的访问权限?
【发布时间】:2017-08-22 12:25:52
【问题描述】:

我正在编写一些代码,我遇到了类似的情况:

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 而不是Foofriend,因为除了Foos 构造函数Bar 不需要访问任何Foos 私有方法(因此不应该拥有使用权)。有没有办法只允许Bar 创建Foos 而不让他们成为朋友?

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

【问题讨论】:

    标签: c++ constructor private friend


    【解决方案1】:

    这正是attorney-client 成语的用途:

    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;
    }
    

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

    【讨论】:

    • 感谢您将“不。但是...”评论变成了一个不错的答案。我已经担心有一个原因我不能将它用于构造函数
    • @tobi303 很抱歉吓到了。发表评论两秒钟后,我意识到我试图在评论中回答您的问题。
    【解决方案2】:

    如果不想再介绍类,可以缩小朋友圈,和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;
    }
    

    这并不能完全达到你想要的效果,但它会让友谊更有针对性。

    【讨论】:

    • 为什么不正是我想要的?不幸的是,目前Bar 需要知道Foos 的定义,但如果解决了友谊问题,这可能会改变一次。
    • @tobi303 这不是您想要的,因为您要求限制朋友可以做什么,而这种方法反而限制了谁是朋友。 Bar 的构造函数由于与Foo 的友谊,仍然保留了全范围的访问权限。当然,视情况而定,这可能不是一件坏事。
    • 啊,是的,明白了。其实我不介意如果没有朋友也可以。我根本不喜欢朋友的概念(我的意思是 C++ 一个;)。使用这种方法,至少我必须小心不要做愚蠢的事情的范围被限制在最小范围内
    【解决方案3】:

    我想到的一种方法是有一个内部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 函数,而直接友谊则不能。

    【讨论】:

    • 我首先考虑的是这个方向,尽管我的解决方案会更加混乱
    • @tobi303 我刚刚意识到这种技术还允许您使用直接友谊不能使用的智能指针。
    猜你喜欢
    • 1970-01-01
    • 2012-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-28
    • 1970-01-01
    • 2022-07-22
    • 2016-05-10
    相关资源
    最近更新 更多