web-dev-qa-db-ja.com

クラスの定数データメンバーをコンストラクターで初期化する必要があるのはなぜですか?

クラスの定数データメンバーをコンストラクターで初期化する必要がある理由と、他の場所で初期化する必要がある理由を知りたいのですが。そうすることとしないことの影響は何ですか?

また、クラス内で初期化できるのは静的定数積分データのみであり、データメンバー以外は初期化できないこともわかります。クラス内で初期化されます。

例:-以下が私のクラス宣言であると仮定します

class A{
     int a; // This we can initialize at the constructor or we can set this member by calling "vSet" member function
     const int b;
     static const int c = 10; //This works fine
public:
     A();
     ~A();
     void vSet(int a);
     int iAdd();
     void vDisplay();    
};

そしてコンストラクターは以下のように定義されます:-

編集されたセクション:前のコンストラクター定義の例が間違っていたため

 A::A():a(1),b(9){}

私が間違っている場合は私を訂正してください。前もって感謝します。

7
Abhineet
A::A(){
      a = 1;
      b = 9; // Why we need to initialize this only at the constructor. 
   }

初期化ではありませんが、割り当て
abはすでに作成されており、この場合はそれらに値を割り当てます。 const修飾子は、変数が初期化後に変更されないことを要求します。これにより、この割り当てによってそのコントラクトが破られる可能性があります。

これは、メンバー初期化リストを使用した初期化です。

A::A():a(1),b(9)
{}

違いを知るために、私のこの答えを見てみたいと思うかもしれません。

コンストラクター内での初期化と代入の違いは何ですか?


別の質問として、クラス内で初期化できるのは静的定数積分データのみです、より詳細に説明している私のこの回答を読んでください:

クラス内の非const静的メンバーまたは静的配列を初期化できないのはなぜですか?

12
Alok Save

あなたがしているのは初期化ではありません。これは割り当てであるため、bconstであるため、b=9はコンパイルされません。したがって、割り当てられた値を指定することはできません。 initializedである必要があります。これを行うには、member-initializationlistを次のように使用します。

A::A() : a(1), b(9) 
{   // ^^^^^^^^^^^^ this is called member-initialization list

}

C++ 11では、インプレース初期化を次のように使用できます。

class A{

     int a = 1;       //C++11 only
     const int b = 9; //C++11 only

     static const int c = 10; //This works fine (both in C++03 and C++11)
     //...
};
9
Nawaz

定数であるため、値を変更することはできません。コンストラクター以外の場所で初期化すると、デフォルトの初期化が続き、その後にassignmentが続きます。これは、定数では許可されていません。 。これを行うのと同じです:

const int i; // OK
i = 42; // Error!

C++ 11では、これを実行してもまったく問題がないことに注意してください。

struct Foo {

  const int i=42;
  const double x = 3.1416;
};

ただし、これは同じルールに従います。つまり、割り当てはありません。

6
juanchopanza

Constデータは、決して変更できないデータです。一度初期化された後、同じ値を永久に保持します。

そのため、どこにでも値を割り当てることはできません。

ただし、コンストラクターは初期化が行われる場所です。したがって、ここでは例外があり、constデータに値を割り当てることができます。これは、初期化リストと同じように、古典的な方法で行うことができます。

さて、変数が静的でないときにクラス定義でこれを行うことができない理由は(たとえばJavaとは異なり)別の問題であり、私には答えがわかりません。

3
Gyscos

コンストラクターのbodyが入力されると、すべてのメンバーとサブオブジェクトはすでに初期化されています。コンストラクターbodyが実行できるのは、changeそれらを実行することだけです。つまり、constメンバーには許可されていません。

ただし、初期化子リストを使用することはできます。

const値は右辺値であることが意図されているため、定数であるため、式の右側に表示することはできません。

したがって、コンストラクターの本体でこの式を使用すると

A::A()
{
    a = 1;
    b = 9; // Why we need to initialize this only at the constructor. 
}

Alsが前述したように、const値を左辺値として使用しています。事実は、存続期間が始まった後、その値を変更することを許可されていない変数に新しい値を割り当てようとしているということです。

定数データメンバーに値を割り当てる正しい方法は、ctor初期化子リストにあります。つまり、メンバー値の有効期間が始まる前です(Nawazが述べたように)。

A::A() :
    a(1),
    b(9)
{
}

最後に、C++ 11標準では 宣言されたすべてのデータメンバーを初期化できます 、staticconstのものと同じです。

1
PaperBirdMaster

コンストラクターの外部でconstメンバーを初期化することはできません。なぜなら、それらはconstだからです。定義上、初期化後に変更することはできません。オブジェクトが構築された後は、値を設定しようとするものはすべて変更です。

1
jamesdlin