2009-08-06 25 views
3

C++では、クラスインスタンスを通じて静的メンバー変数にアクセスしない理由はありますか?私はJavaがこれを嫌に思っており、C++で重要かどうか疑問に思っていました。例:C++:クラスまたはインスタンスを介してconstメンバーにアクセスできますか?

class Foo { 
    static const int ZERO = 0; 
    static const int ONE = 1; 
    ... 
}; 


void bar(const Foo& inst) { 
    // is this ok? 
    int val1 = inst.ZERO; 
    // or should I prefer: 
    int val2 = Foo::ZERO 
    ... 
}; 

私には2番目の質問があります。静的なdoubleを宣言すると、どこかで定義する必要があり、その定義はその型を繰り返す必要があります。なぜタイプを繰り返さなければならないのですか?たとえば :

In a header: 
    class Foo { 
    static const double d; 
    }; 
In a source file: 
    const double Foo::d = 42; 

は、なぜ私は私のCPPファイルの「constのダブル」の部分を繰り返さなければならないのですか?

+2

正確な重複はありませんが、おそらく同じ回答が当てはまると思います。http://stackoverflow.com/questions/840522/given-a-pointer-to-ac-object-what-is-the-preferred-way -to-call-a-static-membe –

+0

はい。インスタンスではなく接頭辞としてクラスを好むべき理由のために、アダム・ローゼンタールの答えを読んでください。 – quark

答えて

5

最初の質問では、スタイルの問題とは別に(クラス変数であり、オブジェクトが関連付けられていないことがわかります)、Fred Larsenは質問にコメントして以前の質問を参照します。 Adam Rosenthal's answerをよく読んでください。あなたはこれに注意したい理由があります。

:あなたの2番目の質問については

(。。彼は答えとして、それを投稿、しかし、私はそれが原因だそう信用できない私はアダムアップ投票しなかったしたい場合、私はアップ票フレッドいただきたいです)

なぜ私のcppファイルで "const double"部分を繰り返す必要がありますか?

この型を主に実装の詳細として繰り返す必要があります。つまり、C++コンパイラが宣言を解析する方法です。ローカル変数に対してもこれは厳密には理想的ではなく、C++ 1x(旧称C++ 0x)は、autoキーワードを使用して、通常の関数変数に対して繰り返し必要がないようにします。だから、

この:

vector<string> v; 
auto it = v.begin(); 

これは非常にあなたのケースのTHOSには、同様に静的では動作しなかった理由は明確な理由はありません:

const double Foo::d = 42; 

vector<string> v; 
vector<string>::iterator it = v.begin(); 

は、このになることができます

となることがあります。

static Foo::d = 42; 

キーが宣言としてこれを識別する一部方法を有することです。私は明確理由言わない

注:C++の文法は生きた伝説である:それはそのエッジ例すべてをカバーするのに非常に困難です。私はしません上記はあいまいだと思うかもしれませんが。そうでなければ、それを言語に加えることができます。それらについて教えてください... C++ 2xの場合:/。

6

Foo::ZEROよりinst.ZEROが好きです。何が起こっているのかがはっきり分かるからです。しかし、クラスFooのメソッドでは、私はちょうどZEROを使用します。

ボーナスの質問については、constは完全なタイプの一部です。

+0

私はconstが型の一部であることを理解しています。私はなぜタイプを繰り返す必要があるのだろうかと思っています。私はちょうど言ってみたい: Foo :: d = 42; ヘッダーファイルにFoo :: dが1つだけ宣言されています。これは私がここで見ていないいくつかのあいまいさの可能性を紹介していますか? dという名前のメンバ関数がありますか?私はタイプを繰り返す良い理由があることを知っている、私はちょうどそれが何であるか分からない。 – criddell

+0

多分それは言語の規則なのでしょうか? – Juan

+0

私はこれをコメントで説明しようとしましたが、部屋から逃げました。私はそれに答えます。 – quark

3

静的と宣言してクラス定数にすると、私はFoo :: Zeroを使用して、あなたのコードのカジュアルでない人に意図を伝えます。

また、Foo :: ZEROをFoo :: Zeroに変えることで、すべての大文字の名前を置き換えることになります。プリプロセッサマクロの通常の規約は、すべて大文字で命名し、C++定数に似た命名体系を使用することでトラブルを尋ねています。なぜなら、プリプロセッサはC++定数を駄目にし、非常に面白いエラーメッセージで終わるからです。

+0

命名規則にうわべい。私は実際にこれで1回以上噛まれました(皆さん、皆さん、#PPIを定義してください!!!) – criddell

1

私はFoo :: ZEROを使用しますが、それは私だけです。特にFooから派生した場合、混乱します。

2番目の質問では、二重値のメモリを作成する必要があります。これは実装単位で発生します。

メモリを作成する必要がない唯一の型はconst型です。その値をヘッダファイルに入れることができます。しかし、アドレスを持たないので、.cppファイルに定義を置かない限り、関数を参照して渡すことはできません。 (これはgccで動作する方法と思われます)。

1

あなたの例で使用するフォームは関係ありません。彼らはどちらも同じことを意味します。私は一般的にクラスの方法を使用したいと思うので、常にドット演算子を使うのに便利なインスタンスを持つとは限りません。

誰かがテンプレート関数を書いていると考えると、両方のオプションを持つとよいです。彼らはドット演算子で関数をコード化しているかもしれません。静的クラスメンバーを持つクラスは、その構文がサポートされているため、テンプレートをインスタンス化するために引き続き使用できます。

あなたのボーナスに関する質問は、言語がそうであるとおりです。完全な型を宣言する必要があります。あなたはおそらくそれを別の質問で尋ねるべきです。

1

個人的に私は匿名の列挙型を使用します。最終結果はまったく同じです:)

ご質問はありません。私は間違いなくあなたがアクセスしているものを見てその明白なので、Foo :: Zeroを好むだろう。 inst.Zeroはあなたの前にどんなタイプのinstがあるか調べる必要があります。

データ型を繰り返す必要があるのは、C++の仕組みだからです。同じようにヘッダファイルに次のように記述した場合。

extern int foo; 

あなたはまだCPPファイル内

int foo 

を言及する必要があります。 pukkuが述べたように、 "const int"型の変数を宣言しています。したがって、 "const int"は変数の定義で繰り返さなければなりません。

+0

匿名のenumは特定のストレージサイズ(int)を強制します。定数を異なる型にする場合は、匿名のenumを使用することはできません。 –

関連する問題