2012-06-15 23 views
5

我々は二つのクラスがあるとします。クラスを他のクラスの特定のプライベートメンバーにしかアクセスできないようにするにはどうすればいいですか?

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::x(とさえへのへのアクセス権を持っているということですその他の私的会員はBaseです)。しかしFooにはBase::f()へのアクセス権が必要です。

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

EDIT:

私は私が必要とするアクセス制限を指定しようとするでしょう。まず、Baseはライブラリ内のインターフェイスです(実際は抽象クラスです)。ユーザーはBaseから派生したクラスのみを使用します。 Base::f()は、ライブラリ内の別のクラスであるFooによってのみ呼び出されます。 Base::f()をユーザーから隠すことは、いつ呼び出すかを知っているのはFooなので、重要です。同時に、FooBaseの他のメンバーを台無しにすべきではありません。あなたはこのようなBaseのデータを含む別のクラスを作成することができます

+0

'f()'を保護し、保護された継承を使用することができます。 – chris

+0

しかし 'Foo'は' Base'から派生したものではありません。 – miloszmaki

+0

それは単なる考えだった。あなたはそれを派生させる必要があります。 'BaseData'の答えを見た後、私はそれに行くだろう。 – chris

答えて

6

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

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

私はこのアプローチが好きです。なぜなら、.cppファイルの 'Base_f_Accessor'の実装の詳細を隠すことができるからです。このように、 'Foo'は.cppファイルで定義することもでき、ユーザーには公開されません。 – miloszmaki

4

class BaseData { 
protected: 
    int x; 
}; 

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

をあなたはxたかったが、ないように、FooBaseの方法としてfにアクセスすることができます。友情は交換可能ではありません。 protectedを使用すると、xは、BaseDataから直接派生したものを除いて、誰にでもプライベートに見えます。

複数の継承を使用してBaseを定義し、が派生するクラスにのみFooアクセス権を付与する方がよい場合があります。ここで

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() {} 
}; 

FooBaseからWith_fのポインタを持っている必要がありますが、それは、その後fメソッドにアクセスすることができました。 Foogにアクセスできませんでした。

+0

あなたは 'Base'を' BaseData'の友人にしたらどうなりますか? 'Base 'の友達もそれにアクセスできますか?私はそれがうまくいくとすれば、継承よりもうまくいくと思う。 – chris

+0

@chris:友人の友人はC++の友人ではありません。 – jxh

+0

それはおそらく継承を導入するよりもうまくいくでしょう。 – chris

2

これを達成するための簡単で非ハッキリな方法はありません。 C++は単にそのようなアクセス制御細分性を持っていません。いくつかの継承で遊ぶことができますが、複雑さが増すとこのアクセス制限の利点よりも優れています。また、このアプローチは拡張されません。あなたは1つのフレンドクラスにのみ許可を増やすことができます。

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"; 
} 
関連する問題