2009-08-29 10 views
4

私は、特にその技術において、C++をかなり新しくしています。私の質問は、どのようにクラス自体の静的オブジェクトメンバを作成することです。私が意味することは、クラス内で静的メンバーオブジェクトを宣言したことです。例:クラスの静的オブジェクトメンバーを作成するにはどうすればよいですか?

CFoo:CFoo *pFoo[2] = {0}; 

class CFoo 
{ 
    public: static CFoo *pFoo[2]; 
    public: CFoo(int a); 
    public: CFoo *getFoo(); 
}; 

今の問題は、私は私のいずれかを返すことからgetfooメソッドを使用することができるように、2つの静的オブジェクトpFoo、

pFoo[0] = new CFoo(0); 
pFoo[1] = new CFoo(1); 

を作成するように私は、pFooを作成する方法であり、 pFooのように、

CFoo *getFoo() 
{ 
    return pFoo[0]; //or pFoo(1); 
} 

ありがとうたくさんの人。私の質問ははっきりしていると思う。

もう一度お返事ありがとうございます。 -sasayins

答えて

19

コードを一度に1ステップずつ改善しましょう。私は各ステップで何をしているのか説明します。

ステップ1、これはJavaではありません。すべてのメンバーに公開を指定する必要はありません。 public:の後のすべては、何かを指定するまで公開されます(protectedまたはprivate)。私はまた、クラスの後にpFooの定義を移しました。変数が宣言される前に定義することはできません。あなたはgetFooメンバ関数を持っているつもりなら

class CFoo 
{ 
    public: 
     static CFoo *pFoo[2]; 
     CFoo(int a); 
     CFoo *getFoo(); 
}; 

CFoo* CFoo::pFoo[2] = {0}; 

ステップ2、pFooはおそらく、公開すべきではありません。内部データを公開する代わりに、インターフェイスをクラスに適用しましょう。

手順3では、newを使用することなくポインタで戻すことができます。私は長年にわたりC++コードを書いており、静的メンバー変数のために新しいメモリがどのように更新されたのか調べなければなりません。それを把握するのは面倒なことではないので、スタックにそれらを割り当てるだけです。また、constポインターでそれらを戻し、ユーザーが2つのstatic CFooオブジェクトを誤って変更しないようにしましょう。

class CFoo 
{ 
    public: 
     CFoo(int a); 
     const CFoo *getFoo(); 

    private: 
     static CFoo foos[2]; 
}; 

CFoo CFoo::foos[2] = {CFoo(0), CFoo(1)}; 

getFooの実装では、次のようになります。

const CFoo * CFoo::getFoo() 
{ 
    return &foos[0]; // or &foos[1] 
} 

IIRC、静的メンバfoosあなたはCFooオブジェクトを作成する最初の時間が割り当てられます。だから、このコード...

CFoo bar; 
const CFoo *baz = bar.getFoo(); 

...は安全です。ポインタbazは、静的メンバーfoos[0]を指します。

+1

あなたはたくさんの良い点を挙げています。私はあなたに3つの票を与えたいと思います。 – sbi

+0

+1良いアドバイス。また、あなたが明示的にそれをしない限り、静的メンバーに与えられたメモリを解放する本当に信頼できる方法はありません。プログラムが終了するまで割り当てられたままになります。 –

+0

素敵なおかげです。しかし、もし私がCFooを使ってオブジェクトを作成したいとしたら、例えば CFoo * pFoos [2]; pFoos [0] =新しいCFoo。 pFoos [1] =新しいCFoo。 私の質問は、foos [0]とfoos [1]は割り当てられていますか? – domlao

6

ここにポインタは必要ありません。実際、彼らはおそらく良い考えではないでしょう。

次のコードは、私の作品:

#include <iostream> 

struct Foo { 
    static Foo const foos[]; 

    Foo(int i) : i(i) { } 

    int i; 
}; 

Foo const Foo::foos[2] = { Foo(1), Foo(2) }; 

using namespace std; 

int main() { 
    cout << Foo::foos[0].i << endl; 
} 

()デモをシンプルに保つために(それに注意してください、私はそれは同じように動作し、あなたが望むものではないおそらくすべてのメンバーpublicを、作りました。 。うまくプライベートメンバーと)

3

があなたの配列を初期化するには、このことを書く必要があります。

CFoo* CFoo::pFoo [2] = { new CFoo(0), new CFoo(1) }; 

をメートルを解放しないでくださいエモリーはそのように割り当てられました。

+0

+1「割り当てられたメモリを解放しないでください。」 –

+0

@Pavel:警告:CFooオブジェクトはアプリケーション終了時に自動的に破棄されません(静的初期化と破壊)。 – moala

+0

もちろん、自動的に解放されることはありません。しかし、手動でもそれらを解放するべきではありません。 –

2

これを行うにはいくつかの方法があります。一つは、ちょうどあなたがやっているようやり続けると、この

// In source file (not header) 
CFoo* CFoo::pFoo[2] = {new CFoo(1), new CFoo(2)}; 

ようpFoo配列を初期化することである。しかし、私はこのようなアクセサでそれらをラップすることをお勧め:

// In header 
class CFoo 
{ 
public: 
    CFoo(int a); 
    CFoo* getFoo1() const; 
    CFoo* getFoo2() const; 

private: 
    static CFoo* getFoo(int n); 
}; 

// In source file 

CFoo::CFoo(int a) 
{ 
// Constructor implementation 
} 

CFoo* CFoo::getFoo1() const 
{ 
    return getFoo(1); 
} 

CFoo* CFoo::getFoo2() const 
{ 
    return getFoo(2); 
} 

CFoo* CFoo::getFoo(int n) 
{ 
    static CFoo* pFoo[2] = {new Foo(1), new Foo(2)}; 
    return pFoo[n]; 
} 

主な理由は、このことです静的な初期化順序の失敗を回避します。あるクラスに静的変数がある場合、それが初期化されると非決定的になります。特に変数がpublicの場合は危険です。アクセサーで囲むということは、アクセサーが最初に呼び出されたときに変数が初期化されることを意味します。そのため、使用する前に初期化されていることがわかります。また、しばらく使用しないか、まったく使用しないと、怠惰な初期化の利点が得られます。

上記のコードはスレッドセーフではありませんが、ここでスレッドを使用しているかどうかは疑問です。

また、コーディングスタイルを確認する必要があります。クラスをCで始めるのはやや古風な方法ですが、すべての公開関数が奇妙になる前に「public:」を置くと、一度だけ書く必要があります。

関連する問題