限制嵌套结构中的构造函数范围

Con*_*uit 3 c++ c++11

说我有一个令人难以置信的设计类定义如下:

class Outer {
public:
    struct Inner {
        Inner(int innerValue) : foo(innerValue) {};
        int foo;
    };

    Outer(int innerValue) : _inner(innerValue) {};

    const Inner& getInner() const {
        return _inner;
    };

private:
    Inner _inner;
};
Run Code Online (Sandbox Code Playgroud)

我想Outer是能够构造的一个实例的唯一的类Inner,但是在这样一种方式,其他类/功能可以访问_inner.foo时传递给一个参考_inner通过Outer::getInner().这可能吗?有没有更好的方法来实现同等功能?

lee*_*mes 6

我知道这个问题的两个解决方案,我想展示和比较.

解决方案1(friend):

使用该friend关键字,您可以允许其他类访问您的私有函数.(小心使用.)

你可以使Inner私有的构造函数,但结交Outer朋友Inner.请注意,不仅Inner可以调用构造函数,还可以调用任何私有方法Outer.

class Outer {
public:
    class Inner {
        friend class Outer;     // <<---- friend

        // private to Inner but also callable by Outer (because it's a friend):
        Inner(int innerValue) : foo(innerValue) {};

    public:
        // (add public methods here)
        int foo;
    };

    Outer(int innerValue) : _inner(innerValue) {};

    const Inner& getInner() const {
        return _inner;
    };

private:
    Inner _inner;
};
Run Code Online (Sandbox Code Playgroud)

解决方案2(访问键):

不同friend但稍微复杂的不同方法是为构造函数提供仅Outer能够构造的参数(如"键").然后构造函数是公共的,但是其他类将无法调用它,因为它们无法提供执行此操作所需的参数:

class Outer {
    // Our dummy struct which is only constructible by Outer:
    struct ConstructInnerKey {
        // Empty
    };

public:
    struct Inner {
        Inner(int innerValue, Outer::ConstructInnerKey) : foo(innerValue) {};
        //                    ^^^^^^^^^^^^^^^^^^^^^^^^
        //                a key is required (but not used)
        //                to construct an instance of Inner

        // (add public methods here)
        int foo;
    };

    Outer(int innerValue) : _inner(innerValue, Outer::ConstructInnerKey()) {};
    //                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    //                                      make a key and pass it to Inner

    const Inner& getInner() const {
        return _inner;
    };

private:
    Inner _inner;
};
Run Code Online (Sandbox Code Playgroud)

请注意,虽然这看起来会增加性能开销,但事实并非如此.所有内容都经过优化,仅用于在编译期间捕获访问冲突,如您所愿.

比较:

解决方案2的优点是Inner只能授予Outer访问构造函数的权限.因此,只要你想拥有"真正的"私人功能Inner(甚至无法访问Outer),这是一个很好的解决方案.但解决方案1更容易编写和理解(快速和肮脏,可以这么说).