2017-05-13 23 views
4

次のコードが有効であるかどうか不思議です。静的解析によってこのコンストラクタでエラーが発生しています。同じ名前のコンストラクタ引数とメンバ

要約:メンバ変数 'A'はそれ自身で初期化されます。

要約:メンバー変数 'B'はそれ自身で初期化されます。

要約:メンバ変数 'C'は、それ自身で初期化されます。

class Foo 
{ 
public: 
    Foo(int A, int B, int C); 
private: 
    int A; 
    int B; 
    int C; 
} 

Foo::Foo(int A, int B, int C) : 
A(A), 
B(B), 
C(C) 
{} 

私は、これは良い習慣ではない、おそらくしかし、私は、静的解析の警告が偽陽性であるとメンバ変数が正しく初期化されるだろうかどうかを知りたいと思い、変更すべきであることを知っています。

+3

[あなたのアナライザは間違っています](http://stackoverflow.com/a/6185043/1171191) – BoBTFish

+1

これは悪い習慣であるかどうかは完全に意見に基づいています。例えば、誰かが何かのために新しい名前を導入してはいけないということは、まったく必要でないときにそれを使うことを好むと主張することができます。 – user463035818

答えて

2

これらは、初期化リストの指示に従って正しく初期化されます。

確かに、コードのコンパイル、得られます。これらの警告、もちろん無関係です

Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall main.cpp 
main.cpp:6:9: warning: private field 'A' is not used [-Wunused-private-field] 
    int A; 
     ^
main.cpp:7:9: warning: private field 'B' is not used [-Wunused-private-field] 
    int B; 
     ^
main.cpp:8:9: warning: private field 'C' is not used [-Wunused-private-field] 
    int C; 
     ^
3 warnings generated. 


さらに読書:Initializing member variables using the same name for constructor arguments as for the member variables allowed by the C++ standard?


私は、これは良い習慣ではないことを知っています。

どちらも悪くありません。トレードオフは、新しい名前(通常は見える大文字/小文字など)を導入しないことです。私はそれが意見の問題だと思う。

+0

あなたは完璧な複製をリンクしていないのですか? – user463035818

+0

@ tobi303正しいが、私は答えを書いた後にそれを見つけた。質問を偽装としてクローズするべきでしょうか?すでにやりました! ;) – gsamaras

2

はい、これは偽陽性です。メンバーの初期化リストの式を評価するときは、コンストラクタのパラメータがメンバーよりも優先されます。同時に、コンストラクタパラメータはメンバー名の解決プロセスに参加しないため、すべてが期待どおりに動作します。

これは悪い習慣であるというあなたの意見も完全に有効です。

+0

[tag:language-lawyer]タグを追加しました。これを参考にしてください。 –

2

これは異なるスコープのため、これはかなり有効です。メンバ初期化子リストA(A)の場合、最初のAがクラスのスコープ内にある場合、データメンバAが見つかります。 2番目のA(かっこ内に置かれている)がコンストラクタのスコープ内にある場合、パラメータAが見つかる(同じ名前のデータメンバを非表示にする)。標準から

引用、

$15.6.2/2 Initializing bases and members [class.base.init]:MEM-イニシャライザ-IDで

その範囲内に見つからない場合、最初の修飾されていない識別子は、コンストラクタのクラスの範囲内で検索されコンストラクタの定義を含むスコープで参照されます。

$15.6.2/15 Initializing bases and members [class.base.init]

式リストまたはMEM-初期 のブレース-INIT-listに MEM-イニシャライザが指定されたコンストラクタの範囲で評価されている名前

。 [例:

class X { 
    int a; 
    int b; 
    int i; 
    int j; 
public: 
    const int& r; 
    X(int i): r(a), b(i), i(i), j(this->i) { } 
}; 

は、X​::​aを参照するためにX​::​rを初期化するコンストラクタパラメータiの 値とX​::​ Bを初期化し、コンストラクタパラメータiの 値とX​::​iを初期化し、の 値とX​::​jを初期化しますX​::​i;これはクラスXのオブジェクトが であるたびに行われます。 - end example] [注意:mem-initializerはコンストラクタのスコープ内で評価された であるため、 オブジェクトを参照するmem-initializerの式リストで ポインタを使用して初期化します。 - 最後のノート]

関連する問題