在实施自定义数据结构时,我遇到了一个有趣的困境。不幸的是我在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中检查)
答案 0 :(得分:1)
除了解释它的副本之外,你实际上可以通过使内部类的成员为private并将外部类声明为{{1}来提高私有类作者的意图。 }}。这样你的秒示例(friend
)将不再编译(实际上,添加一个显式的,因此也是私有的copy-ctor):
create
这可确保class Nested {
Nested(int x) : _x(x) {}
int _x;
friend class Enclosing;
};
的所有实例都是从Nested
创建的。