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

时间:2014-07-12 17:57:08

标签: 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;
};

我希望Outer成为唯一能够构造Inner实例的类,但是当传递对{的引用时,其他类/函数可以访问_inner.foo {1}}到_inner。这可能吗?有没有更好的方法来实现同等功能?

1 个答案:

答案 0 :(得分: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;
};

解决方案2(访问密钥):

没有friend但稍微复杂一点的另一种方法是给构造函数一个只有Outer能够构造的参数(比如&#34; key&#34;)。然后构造函数是公共的,但其他类将无法调用它,因为它们无法提供执行此操作所需的参数:

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

请注意,虽然这看起来会增加性能开销,但事实并非如此。所有内容都经过优化,仅用于在编译过程中捕获访问违规行为。

<强>比较

解决方案2的优势在于Inner仅授予Outer访问构造函数的权限。所以只要你想拥有真正的&#34; Inner中的私有函数(Outer甚至无法访问),这是一个很好的解决方案。但解决方案1更容易编写和理解(快速和脏,可以这么说)。