7

2つのクラスがあるとします。

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

class Foo
{
    // some variables and methods
};

今では誰でも電話をかけることができますBase::f()が、私はそれができるようになりたいだけFooです。

この効果を達成するために、私たちはプライベートにして友達としてBase::f()宣言することができます:Foo

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

このアプローチの問題は、と(およびの他のプライベートメンバー)のFoo両方にアクセスできることです。しかし、私はにしかアクセスできません。Base::f()Base::xBaseFooBase::f()

クラス(または関数)が別のクラスの特定のプライベートメンバーにのみアクセスを許可する方法はありますか?または、誰かが私の問題へのより良いアプローチを提案することができますか?

編集:

必要なアクセス制限を指定してみます。まず、Baseライブラリ内のインターフェイスです(実際には抽象クラスです)。ユーザーは、から派生したクラスのみを使用しますBase。ライブラリ内の別のクラスであるBase::f()によってのみ呼び出されます。Fooユーザーから身を隠すBase::f()ことは重要です。なぜなら、Fooいつ呼び出すかしかわからないからです。同時に、Fooの他のメンバーを台無しにしないでくださいBase

4

4 に答える 4

7

非常にハッキーですが、これにより非常にきめ細かいアクセスが可能になります。

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アクセスできますが、できません。友情は可換ではありません。を使用すると、から直接派生したものを除くすべての人に非公開になります。fBasexprotectedxBaseData

より良いアプローチは、多重継承を使用してを定義し、派生元のクラスへのアクセスのみをBase提供することです。FooBase

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にアクセスできます。アクセスできませんでした。fFoog

于 2012-06-15T15:20:52.417 に答える
3

それを達成するための簡単でハックのない方法はありません。C ++には、このようなアクセス制御の粒度がありません。ある程度の継承で遊ぶことはできますが、複雑さが増すと、このアクセス制限が持つ可能性のある利点よりも重要になります。また、このアプローチは拡張性がありません。1つのフレンドクラスにのみ増加したアクセス許可を付与できます。

于 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 に答える