好吧 - 如果你想要你所描述的,那么朋友是最好的解决方案。每个编码标准都建议不要使用朋友,但替代设计更复杂 - 那么也许值得例外。
要解决没有朋友的问题将需要不同的架构
一种解决方案可能是使用一种形式的pImpl 习惯用法,其中“B”派生自内部实现对象,而其他客户端派生自外部类。
另一个可能是在“A”和“其他客户端”之间放置一个额外的继承层。就像是:
class A {
public:
void foo ();
void bar ();
};
class B : public A { // OK access to both 'foo' and 'bar'
};
class ARestricted : private A {
public:
inline void foo () { A::foo (); }; // Forwards 'foo' only
};
但是,这种解决方案仍然存在问题。'ARestricted' 无法转换为 'A',因此这需要通过 'A' 的其他“getter”来解决。但是,您可以以不会被意外调用的方式命名此函数:
inline A & get_base_type_A_for_interface_usage_only () { return *this; }
在尝试考虑其他解决方案并假设您的层次结构需要如您所描述的那样,我建议您只使用朋友!
编辑: 所以xtofl建议将类型“A”重命名为“AInternal”,将“ARestricted”类型重命名为“A”。
那行得通,只是我注意到“B”不再是“A”。但是,AInternal 可以虚拟继承 - 然后“B”可以从“AInternal”和“A”派生!
class AInternal {
public:
void foo ();
void bar ();
};
class A : private virtual AInternal {
public:
inline void foo () { A::foo (); }; // Forwards 'foo' only
};
// OK access to both 'foo' and 'bar' via AInternal
class B : public virtual AInternal, public A {
public:
void useMembers ()
{
AInternal::foo ();
AInternal::bar ();
}
};
void func (A const &);
int main ()
{
A a;
func (a);
B b;
func (b);
}
当然现在你有了虚拟基础和多重继承!嗯....现在,这比一个朋友声明好还是坏?