2012-01-21 6 views
1

現在、特定の種類のクラスによるメソッドの使用を制限する適切な方法を探しています。固有の種類のクラスでしか使用できないメソッドがある

私はサーバー内のネットワーク専用のクラスを持っています(ClientSessionと呼んでください)。一度サーバーに接続されたクライアントは、認証に30秒かかります。そうでない場合、サーバーは接続を閉じます。

認証は、サーバー上の別のクラス(Authenticatorと呼ぶ)によって処理されます。ClientSessionは、クライアントが正常に認証され、30秒のタイマーをキャンセルできると警告します。

問題は、公開メソッドClientSessionを呼び出すには、Authenticatorが必要です。しかし、私はその方法を誰にでも呼び出すことができないようにしたい。

要約すると、AuthenticatorClientSession::clientAuthSuccessful()メソッドを呼び出すことができる唯一のクラスにします。

私は2つの事に見てきました:

  • 友達方法が、私はAuthenticator友達メソッドを介してすべてのプライベートメソッドとプロパティまたはClientSessionにアクセスできるようにしたくありません。
  • 訪問者のデザインパターンですが、私の使い方を誤解していない限り、私は欲しいものをまったくやっていないようです。

このような特定の制限がある方法はありますか?またはクリーンな代替手段ですか?

+0

http://stackoverflow.com/questions/7582664/is-there-a-way-in-c-to-create-super-private-variables/7582721#7582721あなたが探しているものかもしれません。しかし、私はちょうどよい古い文書に行きます。 – pmr

答えて

1

もっと簡単な方法があります。 ClientSessionから特別な目的のコードをAuthenticatorに渡すだけです。これは、関数ポインタ、関数オブジェクト、またはラムダ関数を使って実現できます。

class ClientSession 
{ 
public: 
    void startSession (Authenticator& authenticator) 
    { 
     // pass function pointer to method to call when 
     // the timeout for authentication has elapsed. 
     authenticator.start(this, &ClientSession::warnThat30SecsHasPassed); 

     // alternative syntax, using new lambda function syntax, 
     // which will end up reducing coupling between the two classes. 
     authenticator.start([this](){ warnThat30SecsHasPassed() }); 
    } 
private: 
    void warnThat30SecsHasPassed() { ... } 
}; 

class Authenticator 
{ 
public: 
    // classic way. 
    void start (ClientSession * session, void(ClientSession::*callback)()); 

    // using new syntax. 
    void start (std::function<void()> callback); 
} 
+0

アイデアをありがとう、それはメソッドのプライバシーを '強制的に'バイパスするための良い方法のように思えます。私は以前ラムダ関数を調べていませんでした。私は理解するまでに時間をかけました(そして、私はまだ完全な考えを持っているのか分かりませんが、関数ポインタを使うときは新しいスコープを入力するのを避けているようです)。それが一番きれいなのかどうかはわかりませんが、私はそれを使うかもしれません。ありがとう。 – Jukurrpa

+0

@Jukurrpa:C++のラムダ関数がC++ 11まで不足しているため、これは(まだ)C++を記述する慣習的な方法ではありませんが、C#を含む多くの言語でこの問題を扱う一般的な方法です。ラムダ関数のサポートがより普及するにつれて、私はこの手法がより一般的になるだろうと考えています。 –

+0

私はラムダ式をよりよく理解しているので、あなたの答えをもう一度読んでくれました。それは私にとって、最も簡単で簡単な解決策です。再度、感謝します。 – Jukurrpa

1

いいえ、これを行うのはクリーンな方法ではありません。あなたは友人のクラス、またはパブリックメソッドを使用します。

クリーンウェイは不可能ではありません。私はこのようなコードを書くことはない、とあなたは必要がありますが、以下の要件に従っていどちら:、class B以来

class Lock 
{ 
    friend class B; 
private: 
    Lock() {}; 
}; 


class A 
{ 
public: 
    A() {} 
    void foo(Lock x){} 
}; 

class B 
{ 
    void foo() 
    { 
     Lock l; 
     A a; 
     a.foo(l); 
    } 
}; 

Lockインスタンスを作成することができる唯一のクラスであり、そしてA::fooをパラメータとしてLockインスタンスが必要ですそれはBによってのみ呼び出すことができます。

これはしないでください。ヘッダーにコメントやドキュメントを追加することをお勧めします。

+0

それは本当にかなり醜いように見えます。これは多少「共通の」問題ではありませんか?私がこの種の制限をする必要があるのは初めてではありませんが、私はそれについて何も見つけていません...これは、私が作ったデザインが「きれい」ではなく、物事を行うための全く別の方法。 – Jukurrpa

+0

私はそれが 'パスキー'イディオムと呼ばれると思います。 – pmr

+0

@Jukurpaおそらくもっとクリーンなデザインですが、おそらくもっと多くのリファクタリングが必要になるでしょう。また、問題が頻繁に遭遇するだけで解決策があるわけではありません。 C++にはリフレクションがありません。Javaには友人がいません。 –

0

ClientSession友人とその同僚のAuthenticatorというプロキシクラスを作成できます。

+0

これは多分同じ問題です。プロキシクラスはすべてのClientSessionメンバーにアクセスできます...そしてさらに私はプロキシを信頼していますが、他のメソッドに対してはこのような制限が必要な場合があります。つまり、それぞれのメソッドのプロキシクラスを意味します。 – Jukurrpa

+0

いいえ、それはありません。友情は推移的ではありません。私の友人の友人は私の友人ではありません。 (それは10倍速いと言ってください)それには、多数の組み合わせがある場合は不器用で、それには反対しません。 – smparkes

+0

@smparkes:OPが言ったことは、推移性とは関係がありません。 'ClientSession'の友達が' Authenticator'の場合、 'Authenticator'は、単一のメソッドだけでなく、' ClientSession'のprivateメンバーの* all *にアクセスできます。 –

0

問題に直面すると、解決方法に関するアイデアが頻繁に現れ、その解決策を実装するための努力をします。場合によっては、問題を再訪して他のソリューションについて考えるのが良いでしょう。例えば、むしろ、(それに渡さコールバックのいくつかの並べ替えを呼び出すことによって、まだ良いか)、それに渡されたClientSessionを通知するAuthenticator試みを持つよりも

どの程度せるClientSession(またはいくつかの他のオブジェクト/スレッド)はAuthenticator::waitForAuthentication(int timeout)のようなメソッドを呼び出しますか?


編集:私はコールバック概念について詳しく説明しようと思いました。ポイントは、Authenticatorはその仕事をするためにClientSessionクラスの知識を必要としないということです。関数や他の呼び出し可能関数を呼び出すだけでよい。

だから、あなたは右の署名の一部std::functionオブジェクトを受け取るメソッドを持っている、とClientSession(または何を)持っているに渡すために、適切なものを作成するためにあなたのAuthenticatorを書く。それは何Luchianに似た、特殊な関数オブジェクト可能性がありGrigoreは示唆している。たぶんそれは少し一般的なオブジェクト、またはClientSessionオブジェクトのプライベート部分への参照で初期化されるオブジェクトかもしれません。または、C++ 11を使用できる場合はラムダです。私は(完全にまたは他の何か)waitForAuthenticationメソッドを持つ疑いがある、と述べた

は非常によくあなた本当には、あなたのアプリケーションのために何をしたいかもしれません。

+0

さて、私はメッセージを渡すための他の方法について考えようとしましたが、事は 'ClientSession'が他のものを処理しなければならず、特に応答を待つことができないか、時間は私にはきれいに見えません。 – Jukurrpa

+0

オブジェクトのメッセージキューを設定するのが一般的です。メッセージを渡すには、メッセージを適切なキューにドロップするだけです。 'ClientSession'と' Authenticator'だけがそのキューへの参照を取得していることを確認すれば、私はあなたのニーズに合っていると思います。 – Hurkyl

2

(純粋仮想ように)で定義されclientAuthSuccessful()方法で、AuthenticatorListener、インターフェースを定義します。

ClientSessionを個人的にAuthenticatorListenerから継承し、このメソッドを(私的に)実装します。

ClientSessionインスタンスをAuthenticatorに渡すようにします。

このメソッドにアクセスできる他のクラスはありません。 Authenticatorは、適切に分離されたインターフェイスにのみ、ClientSessionに結合されません。

+0

仕事をしているようで、きれいです。ありがとう! – Jukurrpa

+0

本当に、私が考えなかったことがあります。 'ClientSession'へのポインタを持つクラスは、プライベートメソッドにアクセスするためにそれを' AuthenticatorListener'にキャストするだけです。だから、いくらか安全ですが、まだ完全ではありません。 – Jukurrpa

関連する問題