2

在实现自定义数据结构的过程中,我遇到了一个有趣的困境。不幸的是,我在 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;
    }
};

如果我尝试使用调用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 中检查)

4

1 回答 1

1

除了解释它的副本之外,您实际上可以通过将内部类的成员设为私有并将外部类声明friend. 这样,您的第二个示例 ( create) 将不再编译(实际上,还添加了一个显式且因此私有的 copy-ctor):

class Nested {
    Nested(int x) : _x(x) {}
    int _x;
    friend class Enclosing;
};

这确保了 的所有实例Nested都是从Enclosing.

于 2013-09-16T20:45:55.190 回答