7

假设我们有两个类:

class Base
{
private:
    int x;
public:
    void f();
};

class Foo
{
    // some variables and methods
};

现在每个人都可以打电话Base::f(),但我只想Foo能够这样做。

为了达到这个效果,我们可以设为Base::f()private并声明Foo为friend:

class Base
{
private:
    int x;
    void f();
    friend Foo;
};

这种方法的问题在于它Foo可以同时访问Base::f()Base::x(甚至可以访问 的任何其他私有成员Base)。但我只想Foo访问Base::f().

有没有办法让一个类(或一个函数)只授予对另一个类的某些私有成员的访问权限?或者也许有人可以提出更好的方法来解决我的问题?

编辑:

我将尝试指定我需要的访问限制。首先,Base是库中的一个接口(实际上是一个抽象类)。用户仅使用从Base. Base::f()仅由Foo库中的另一个类调用。对用户隐藏Base::f()很重要,因为只Foo知道何时调用它。同时,Foo也不应该打扰其他成员Base

4

4 回答 4

7

非常hacky,但这将允许非常细粒度的访问。

class Base
{
private:
    int x;
    void f();
    friend class Base_f_Accessor;
};

class Base_f_Accessor
{
private:
    static void f(Base & b) { b.f(); }
    friend class Foo;
}

class Foo
{
    // some variables and methods
};
于 2012-06-15T15:26:08.703 回答
4

您可以创建另一个包含这样的数据的Base类:

class BaseData {
protected:
    int x;
};

class Base : public BaseData {
    friend class Foo;
    void f ();
};

现在,Foo可以像您想要f的那样访问,但不是. 友谊不是可交换的。通过使用,对所有人来说都是私有的,除了那些直接派生自.BasexprotectedxBaseData

更好的方法可能是使用多重继承来定义Base,并Foo仅提供对您想要Base派生的那些类的访问。

class With_f {
    friend class Foo;
protected:
    virtual void f () = 0;
};

class With_g {
protected:
    virtual void g () = 0;
};

class Base : public With_f, public With_g {
    int x;
    void f () {}
    void g () {}
};

在这里,Foo必须有一个指向 的With_f指针Base,但它可以访问该f方法。Foo无法访问g

于 2012-06-15T15:20:52.417 回答
3

没有简单的,非黑客的方式来实现这一点。C++ 根本没有这样的访问控制粒度。您可以使用一些继承,但增加的复杂性超过了此访问限制可能具有的任何优势。此外,这种方法无法扩展——您只能将增加的权限授予一个朋友类。

于 2012-06-15T15:22:09.957 回答
0

也许有点麻烦,但你可以在嵌套类是朋友的地方创建嵌套类,然后你可以为每个嵌套类添加朋友。这给出了某种程度的粒度:

#include <iostream>

class Nesting
{
  friend class Foo;
  class Nested1
  {
    friend class Nesting;
  public:
    Nested1() : i(3) { }
  private:
    int i;
  } n1;
  class Nested2
  {
    friend class Nesting;
    friend class Foo;
  public:
    Nested2() : j(5) { }
  private:
    int j;
  } n2;
  int f() { return n1.i; }
};

class Foo
{
public:
  Foo(Nesting& n1) : n(n1) { }
  int getJ() { return n.n2.j + n.f(); }
private:
  Nesting& n;
};

int main()
{
  Nesting n;
  Foo foo(n);
  std::cout << foo.getJ() << "\n";
}
于 2012-06-15T15:34:38.907 回答