题
我有一个类(A类),它被设计为被其他人编写的其他类继承。我还有另一个类(B 类),它也继承自 A。
B 必须访问 A 的一些成员函数,而其他继承类不应访问这些成员函数。
因此,这些 A 的成员函数对于 B 来说应该是公共的,但对于其他人来说应该是私有的。
在不使用“friend”指令的情况下如何解决它?
谢谢。
编辑:例如我为什么需要它。
class A
{
public:
void PublicFunc()
{
PrivateFunc();
// and other code
}
private:
virtual void PrivateFunc();
};
class B : public class A
{
private:
virtual void PrivateFunc()
{
//do something and call A's PrivateFunc
A::PrivateFunc(); // Can't, it's private!
}
};
解决方案
你说的是:有两套A的子类一组应该可以访问,另一组不应该的。感觉错误仅具有一个品牌亚类(即,B)“看到” A的成员。
如果你的意思是:只有的我们的可以使用的的功能,这个的一部分,而我们的客户不能,还有其他度假胜地
。(通过继承功能的重用经常的拐角处,有这样那样的问题。如果你去实现重用的聚集,你可能会得到周围。)
一个建议:
// separate the 'invisible' from the 'visible'.
class A_private_part {
protected:
int inherited_content();
public:
int public_interface();
};
class B_internal : public A_private_part {
};
class A_export : private A_private_part {
public:
int public_interface() { A_private_part::public_interface(); }
};
// client code
class ClientClass : public A_export {
};
不过,更好的方式是去聚集方式,并分割当前“A”变成了看得见和看不见的部分:
class InvisibleFunctionality {
};
class VisibleFunctionality {
};
class B {
InvisibleFunctionality m_Invisible;
VisibleFunctionality m_Visible;
};
// client code uses VisibleFunctionality only
class ClientClass {
VisibleFunctionality m_Visible;
};
其他提示
您不能。这就是朋友了。
另一种方法是改变你的程序的设计/结构。但是,对于这个提示我需要一些更多的内容。
好了 - 如果你想你所描述什么,然后的朋友的是最好的解决方案。每一个编码标准建议不使用的朋友的,但在另一种设计是比较复杂的 - 那么也许这是值得破例
要解决的问题,而无需朋友将需要不同的体系结构
的一个解决方案可能是使用 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”来解决。但是,你能说出这样这个功能,因为它不能被意外名为:
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);
}
当然,现在你有虚拟基地和多重继承!嗯....现在,是不是单一的的朋友更好或更坏的声明?
我觉得你在这里有一个更大的问题。您的设计似乎并不声音。
1)我认为“朋友”构建体是有问题的开始与
2)如果“朋友”是不是你想要的,你需要重新审视你的设计。
我觉得你要么需要做的东西,仅仅能够完成任务,用“朋友”或开发一个更强大的体系结构。看看一些的设计模式的,我敢肯定你会发现一些有用的东西。
编辑:
看到你的示例代码后,你肯定需要重新拱。 A类可能不是你的控制之下,所以这是一个有点棘手,但也许要你要重新做B类是“有-A”类,而不是一个“是一个”类。
public Class B
{
B()
{
}
void someFunc()
{
A a; //the private functions is now called and a will be deleted when it goes out of scope
}
};
我这找到一个有趣的挑战。这里是我可以解决这个问题:
class AProtectedInterface
{
public:
int m_pi1;
};
class B;
class A : private AProtectedInterface
{
public:
void GetAProtectedInterface(B& b_class);
int m_p1;
};
class B : public A
{
public:
B();
void SetAProtectedInterface(::AProtectedInterface& interface);
private:
::AProtectedInterface* m_AProtectedInterface;
};
class C : public A
{
public:
C();
};
C::C()
{
m_p1 = 0;
// m_pi1 = 0; // not accessible error
}
B::B()
{
GetAProtectedInterface(*this);
// use m_AProtectedInterface to get to restricted areas of A
m_p1 = 0;
m_AProtectedInterface->m_pi1 = 0;
}
void A::GetAProtectedInterface(B& b_class)
{
b_class.SetAProtectedInterface(*this);
}
void B::SetAProtectedInterface(::AProtectedInterface& interface)
{
m_AProtectedInterface = &interface;
}
如果你在哪里要使用这种模式的时候,你可以通过使用模板减少代码。
template<class T, class I>
class ProtectedInterfaceAccess : public I
{
public:
void SetProtectedInterface(T& protected_interface)
{
m_ProtectedInterface = &protected_interface;
}
protected:
T& GetProtectedInterface()
{
return *m_ProtectedInterface;
}
private:
T* m_ProtectedInterface;
};
template<class T, class I>
class ProtectedInterface : private T
{
public:
void SetupProtectedInterface(I& access_class)
{
access_class.SetProtectedInterface(*this);
}
};
class Bt;
class At : public ProtectedInterface <::AProtectedInterface, Bt>
{
public:
int m_p1;
};
class Bt : public ProtectedInterfaceAccess<::AProtectedInterface, At>
{
public:
Bt();
};
class Ct : public At
{
public:
Ct();
};
Ct::Ct()
{
m_p1 = 0;
// m_pi1 = 0; // not accessible error
}
Bt::Bt()
{
SetupProtectedInterface(*this);
m_p1 = 0;
GetProtectedInterface().m_pi1 = 0;
}
如果我理解的话:
- A 将被其他开发人员子类化。
- B 将被其他开发人员子类化并继承自 A。
- A 有一些您不希望外部开发人员通过 B 访问的方法。
我认为如果不使用朋友就无法做到这一点。据我所知,没有办法使超类的成员只能供直接继承者使用。