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

C++ 限制嵌套结构中的构造函数范围,c++,c++11,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

假设我有一个非常做作的类,定义如下:

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
是唯一一个能够构造
internal
实例的类,但是当通过
Outer::getInner()
传递对
\u Inner
的引用时,其他类/函数可以访问
\u Inner.foo
。这可能吗?有没有更好的方法来实现等效功能?

我知道有两种解决方案可以解决这个问题,我想对它们进行演示和比较

解决方案1(
friend
):

使用
friend
关键字,您可以允许另一个类访问您的私有函数。(请小心使用。)

您可以将
内部
的构造函数设为私有,但将
外部
设为
内部
的朋友。请注意,
外部
可以调用
内部
的构造函数和任何私有方法

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的优点是
内部
仅授予
外部
访问构造函数的权限。因此,只要您想在
内部
中拥有“真正”的私有函数(甚至不能通过
外部
访问),这是一个很好的解决方案。但是解决方案1的编写和理解要容易得多(可以说既快又脏)。

您能将构造函数设置为私有的,然后使
外部
成为
内部
的朋友吗?“我现在没有时间去验证这个想法。”约瑟夫曼斯菲尔德——事实证明我们可以!见下面leemes的回答。他们也发布了第二个解决方案,我认为这相当新颖。啊,呸!这可能会对我有用-现在就让我做一个不那么做作的尝试…@Nate我补充了另一种方法:)偷偷摸摸。在我的用例中,friend版本可以很好地工作,因为在Internal中不存在其他私有函数——不过,对于将来的问题,我一定会记住access key解决方案。谢谢
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;
};