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