2009-08-28 9 views
0

私はMSNP15プロトコルを実行するクラスを持っています。このプロトコルでは、クライアントは、ディスパッチサーバー、ログインサーバー、およびスイッチボードサーバーなどのさまざまなサーバーへの頻繁な接続/切断を実行する必要があります。C++クラスの設計上の問題

Iは、以下のようなユーティリティクラスの静的メンバ変数として(チケットトークンなど、ナンスなど)プロトコルに関連する変数を格納することを決定した:次いで、上記の静的変数は、起動時にNULLに初期化され

class MsnUtility 
    { 
    public: 
     static void SetChallengeStringL (const char *string); 

     static const char* GetChallengeString (); 

     static void SetContactTicketL (const char *ticket); 

     static const char* GetContactTicket (); 

    private: 

     MsnUtility(); 

    static char *iChallengeString; 

     static char *iContactTicket; 
    }; 

とプロトコルが実行されるときにトークンが利用可能になったときに新しくされました。

私はC++標準ライブラリ(Symbian S60プラットフォームで開発中)にアクセスできないため、文字列ライブラリは使用できません。割り当てられた文字ポインタは、プログラムが終了したときに解放されるか、解放されることを確実にするための他のメカニズムがありますか?

代替デザインの提案もあります。

+0

あなたは小さな文字列クラスを作成してみませんか?賢くなる必要はありません、単純なものは裸のポインタよりも良いでしょう。もしあなたが敢えていなければ、いくらか古くて良いC++の本を選んでください。一度文字列クラスを書くことは、C++プログラマのための非常に一般的な屋内スポーツであり、標準ライブラリよりも前の文章で記述する必要があります。もはやC++の初心者でないなら、これは午後または1日以上かかるべきではありません。 – sbi

答えて

1

あなたがメモリを割り当てる場合、あなたはそれを解放する必要があります一つです。メンバは静的なので、クラスのインスタンスには属しません。したがって、文字ポインタの最後の使用後にメモリが解放されるようにする必要があります。これはしばしば決定することが非常に困難です。

このケースでは、必要なすべてのトークンを持つシングルトンクラスを持つ方がよいと思います。このクラスをグローバルにアクセス可能にし、トークン操作に必要なsetters \ getterを提供します。次に、プログラム終了時にシングルトンクラスのdtorが呼び出されると、メモリの割り当てを解除することができます。次の行に

何か: - それは、基本的にすべてのインスタンスがします -

class TokenDict { 
public: 
    static TokenDict& instance() { 
    static TokenDict instance; 
    return instance; 
    } 
    // getters \ setters for tokens 
    void setToken(char* tptr) { 
    if(token1) 
     delete[] token1; 
    // allocate memory for new token here 
    token1 = new char[strlen(tptr) + 1]; 
    // copy tptr into token1 
    } 
    char const* getToken() const { return token1; } 
private: 
    ~TokenDict() 
    { 
    delete[] token1; 
    } 
    TokenDict() : token1(0) // ctor hidden 
    { } 
    TokenDict(TokenDict const&); // copy ctor hidden 
    TokenDict& operator=(TokenDict const&); // assign op. hidden 
    char* token1; 
}; 
+0

これはどのように「dict」ですか?私は、単一文字配列のラッパーしか見ることができません。なぜデストラクタは公開されていますか? – Ropez

+0

@Ropez:うーん、いいキャッチ。 dtorはプライベートにすることができます。先日、ちょうど入力されました。 Abtの 'dict'は、地図の種類のインタフェースでトークンをラップするか、別々のトークンとして持つかのヒントでした。検索機能が必要な場合、トークンはchar のセットに含まれている可能性があります.CStrCmpはchar *のカスタムコンパレータです。 – Abhay

0

終了後にリークを心配する必要はないと思います。 また、プログラムのライフタイム中にリークを考えている場合は、参照カウントでシングルトンを実行してください。

+1

*ほとんどのプラットフォームはアプリケーションのメモリを再利用しますが、与えられたものではありません。私が正しくリコールすれば、Win98はそうしなかった。 Symbian OSの場合は、http://discussion.forum.nokia.com/forum/showthread.php?t=149695 – outis

+0

をチェックしてください。その場合は、2番目の解決策「参照カウント付きのシングルトン」に進みます。 :-) – Learner

+0

"参照カウント付きのシングルトン"を教えてください。何の参照カウント?プログラム終了時にメモリを再利用するかどうかは問題ではなく、MsnUtilityクラスの適切な設計は問題ありません。 –

0

あなたはクラスMsnUtilityの複数のインスタンスを使用するつもりなら、それの一部だとしてフィールドが静的であることを、予めご了承ください同じである。これはシングルトンと呼ばれ、おそらくあなたが行っていたものではありません。

+0

Maciek:私はMsnUtilityの複数のインスタンスを必要としません。すべての必要なプロトコル変数と関連するセッター/ゲッターメソッドを含む単なるインスタンス。 – ardsrk

1

すべての変数が静的である場合、なぜクラスが必要ですか?クラスのインスタンスを1つしか必要としない場合は、それをシングルトンにすることを検討してください。次に、コンストラクタとデストラクタを使用してメモリを管理することができます。私はシングルトンとして、クラス設計し直す:

class MsnUtility 
{ 
public: 
    static MsnUtility& Instance() 
    { 
    return instance; 
    } 
public: 
    void SetChallengeStringL(const char* cstring) 
    { 
    if (iChallengeString) delete[] iChallengeString; 
    iChallengeString = new char[strlen(cstring) + 1]; 
    strcpy(iChallengeString, cstring); 
    } 
    const char* GetChallengeString() const 
    { 
    return iChallengeString; 
    } 
    void SetContactTicketL(const char* ticket) 
    { 
    if (iContactTicket) delete[] iContactTicket; 
    iContactTicket = new char[strlen(ticket) + 1]; 
    strcpy(iContactTicket, ticket); 
    } 
    const char* GetContactTicket() const 
    { 
    return iContactTicket; 
    } 
private: 
    MsnUtility() : iChallengeString(0), iContactTicket(0) { } 
    ~MsnUtility() 
    { 
    if (iChallengeString) delete[] iChallengeString; 
    if (iContactTicket) delete[] iContactTicket; 
    } 
    char* iChallengeString; 
    char* iContactTicket; 
    static MsnUtility instance; 
}; 

あなたはこのようなクラスを使用することができます:

// test.cpp 

#include <iostream> // or whatever is available on your development platform. 
#include "MsnUtility.h" 

MsnUtility MsnUtility::instance; 

int 
main() 
{ 
    MsnUtility& u = MsnUtility::Instance(); 
    u.SetContactTicketL("ticket"); 
    u.SetChallengeStringL("ch"); 
    std::cout << u.GetContactTicket() << ", " << u.GetChallengeString() << '\n'; 
    return 0; 
} 
+0

Vijay、インスタンスは静的なクラス変数である必要がありますか? instaceをローカル静的変数にしてAbhayの示唆しているようにMsnUtility :: Instance()メソッド自体に宣言すると、どのような欠点がありますか? – ardsrk

+0

インスタンスをInstance()の静的変数にすると、他のメンバ関数はそれを直接使用することができません。つまり、そのスコープはInstance()に限定されています。もちろん、他のメンバ関数は "インスタンス"を使うことができますが、関数呼び出しのオーバヘッドがあります。インスタンスを静的なローカル変数にすることは、現在の要件では問題ありませんが、今後さらに多くの機能が追加されると問題になる可能性があります。 –

+1

@Vijay:私は同意しない。コンパイラが関数をインライン化するため、他のメンバ関数はおそらくシステムコールのオーバーヘッドなしにinstance()を使用できます。しかし、もっと重要なのは、他のメンバ関数は代わりに 'this'を使うべきです。 – Ropez

0

私は、あなたがQt Towerプロジェクトに見ることができると思い、それはまだ初期段階にあるが、それは持っていますUIを含む豊富なクラスライブラリ。