2009-02-02 133 views
3

我有一个类(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! 
    } 
}; 
+0

请问你能写出为什么你需要这种方式吗? – 2009-02-02 18:49:00

+0

那么,代码示例说明了为什么你需要它的语法,而不是为什么你需要它在设计方面。对于这样一个小事情,朋友做它应该做的事情。有多少派生类需要朋友访问? > 1? – gimpf 2009-02-02 21:45:05

回答

3

你说的是:有两套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; 
}; 
0

如果我的理解:

  • A将被其他开发者继承。
  • B就被其他开发者的子类和继承A.
  • A有一些方法你不想通过B.给外部开发者访问

我不认为这可以在不进行使用朋友。我不知道如何让超类的成员仅用于指导继承者。

4

你不能。这就是朋友的用途。

另一种方法是更改​​程序的设计/体系结构。但对于这个提示,我需要更多的上下文。

1

我想你在这里遇到了更大的问题。你的设计看起来不太好听。

1)我觉得“朋友”结构是有问题开始与

2)如果“朋友”是不是你想要的,你需要重新审视你的设计。

我认为你需要做一些只是完成工作,使用'朋友'或开发更强大的架构。看看somedesign patterns,我相信你会发现一些有用的东西。

编辑:

看到你的示例代码后,你肯定需要重新拱门。 A类可能不在你的控制之下,所以这有点棘手,但可能希望你想重新做B班,成为“有一个”班而不是“is-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 
    } 

}; 
1

好 - 如果你想你所描述什么,然后朋友是最好的解决方案。每个编码标准建议不要使用朋友,但其他设计更复杂 - 那么也许值得做个例外。

为了解决不朋友的问题需要一个不同的体系结构

一种解决方案可以是使用其中“B”从内实现对象导出pImpl idiom的一种形式,而其它客户端从外类派生。

另一个可能是在'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); 
} 

当然现在你有虚拟基地和多重继承!嗯....现在,是比单朋友声明更好或更差?

+0

如果您随后将A重命名为A_Internal,并将其重命名为A,那么您就是你想要的地方。 – xtofl 2009-02-02 18:52:49

1

我觉得这是一个有趣的挑战。下面是我将如何解决问题:

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