我有一个类(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 访问的方法。

我认为如果不使用朋友就无法做到这一点。据我所知,没有办法使超类的成员只能供直接继承者使用。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top