在封闭类的公共接口中使用私有嵌套类

时间:2013-09-16 20:33:21

标签: c++ c++11

在实施自定义数据结构时,我遇到了一个有趣的困境。不幸的是我在C ++ 11标准中找不到任何答案,所以我希望有人可以向我解释。

有一个类有一个私有嵌套类。它还使用此私有子类作为公共函数中的返回值。像这样:

class Enclosing {
private:
    // Private nested class
    struct Nested {
        Nested(int x) : _x(x) {}
        int _x;
    };

    Nested _nested;

public:
    Enclosing():_nested(42) {}

    // Use private nested class in public interface
    const Nested& get_nested() {
        return _nested;
    }
};

如果我尝试使用call get_nested进行编译,虽然我无法创建类型为Enclosing::Nested的局部变量来存储结果。但这是auto拯救的地方:

int main() {
    Enclosing e;
    //Enclosing::Nested n = e.get_ref( ); //Error! Enclosing::Nested is private
    auto n = e.get_nested( );             //Ok, unless we name a type
    cout << n._x << endl;
}

更重要的是,通过一些可变参数模板,我甚至可以调用嵌套类的构造函数并创建它的新示例:

template<class T, typename... Args>
T* create(const T& t, Args... args) {
    return new T(args...);
}

int main() {
    Enclosing e;
    // We can even create a new instance of the private nested class
    auto np = create(e.get_nested( ), 68); 
    //Enclosing::Nested* np = create(e.get_nested( ), 68); // But don't name a type
    cout << np->_x << endl;
}

可以请任何人向我解释这种行为吗?为什么auto允许我们访问其他私有数据类型?必须有一些我到目前为止看不到的明显原因。我们非常欢迎参考标准中的段落。

非常感谢!

(在gcc 4.7.3和clang 3.2中检查)

1 个答案:

答案 0 :(得分:1)

除了解释它的副本之外,你实际上可以通过使内部类的成员为private并将外部类声明为{{1}来提高私有类作者的意图。 }}。这样你的秒示例(friend)将不再编译(实际上,添加一个显式的,因此也是私有的copy-ctor):

create

这可确保class Nested { Nested(int x) : _x(x) {} int _x; friend class Enclosing; }; 的所有实例都是从Nested创建的。