我正在开发C ++类库。这些类具有针对用户的“公共”方法,而“受保护的”方法提供保留供内部使用的额外服务。
这些类不是彼此派生的。在我当前的模型中,需要将它们明确声明为彼此的朋友。有没有更紧凑/方便的方法来达到相同的效果?
示例:
class A
{
public:
static int ExposedA() { return 1; }
static int ExposedB();
static int ExposedC();
private:
static int Internal() { return 0; }
friend class B;
friend class C;
};
class B
{
public:
static int ExposedA() { return 2 + A::Internal(); }
static int ExposedB() { return 2; }
static int ExposedC();
private:
static int Internal() { return 0; }
friend class A;
friend class C;
};
class C
{
public:
static int ExposedA() { return 3 + A::Internal(); }
static int ExposedB() { return 3 + B::Internal(); }
static int ExposedC() { return 3; }
private:
static int Internal() { return 0; }
friend class A;
friend class B;
};
int A::ExposedB() { return 1 + B::Internal(); }
int A::ExposedC() { return 1 + C::Internal(); }
int B::ExposedC() { return 2 + C::Internal(); }
在实践中,维护好友列表非常繁琐,并且前向引用迫使将定义移出类。
答案 0 :(得分:0)
我认为简短的答案是“不”。
在评论中(供以后阅读的任何人使用),您将问题标识为“ 故意强耦合的情况”,如an answer to this question(强调我的)中所述:< / p>
通常,朋友类在有故意强耦合的设计中很有用:您需要在两个类之间建立特殊的关系。更具体地说,一个班级需要访问另一个班级的内部信息,而您不想使用公共访问说明符向所有人授予访问权限。
答案继续说明:
经验法则:如果public太弱而private太强,则需要某种形式的选定访问:受保护的或朋友的(Java中的程序包访问说明符起着相同的作用)。
换句话说,如果public
对您不起作用,而private
对您不起作用,那么您将剩下protected
和friend
。如果您也无法使用protected
,那么您将在淘汰过程中陷入friend
的困境。您无法更改语言(除非您想向委员会提交论文,但这完全是另一个主题)。您将尽最大努力来处理这些访问说明符。
关于哪种方式是使用这些说明符的最佳方式的问题,我没有答案。我几乎不可能知道哪种杂耍组合最适合您的情况。到目前为止,您的解决方案似乎是最好的。鉴于您的限制,没有什么比这更好的了。
它在类库的内部。用户应该没有访问权限,类中的库应该具有相互访问权限。
如果我正确地理解了您(可能不是),我会说您确实具有(未调试的)双重标题选项:一个供您使用,一个供最终用户使用。在标题中,您可以使函数public
像这样:
// YouB.h
class B
{
public:
static int ExposedA() { return 2 + A::Internal(); }
static int ExposedB() { return 2; }
static int ExposedC();
// This is a public function. Your compiler should have no problem with other classes using it
static int Internal() { return 0; }
};
然后,您为用户使用了不同的标题:
// UserB.h
// YouB.h
class B
{
public:
static int ExposedA() { return 2 + A::Internal(); }
static int ExposedB() { return 2; }
static int ExposedC();
private:
// This is a now a private or protected function.
// I haven't tested this, so I don't know if the other access thing will work,
// but since it's solely an internal function, commenting it out or removing
// it completely should work too
static int Internal() { return 0; }
};