クラスのconstメンバー変数を初期化する方法は?


105
#include <iostream>

using namespace std;
class T1
{
  const int t = 100;
  public:

  T1()
  {

    cout << "T1 constructor: " << t << endl;
  }
};

constメンバー変数tを100で初期化しようとすると、次のエラーが発生します。

test.cpp:21: error: ISO C++ forbids initialization of member t
test.cpp:21: error: making t static

const値を初期化するにはどうすればよいですか?


8
c ++ 11でこれは可能です。このリンクをチェックしてください。stackoverflow.com
questions/13662441/

回答:


122

const変数が変更可能かどうかの変数を指定します。割り当てられた定数値は、変数が参照されるたびに使用されます。割り当てられた値は、プログラムの実行中に変更できません。

Bjarne Stroustrupの説明はそれを簡単に要約します:

クラスは通常、ヘッダーファイルで宣言され、ヘッダーファイルは通常、多くの変換単位に含まれます。ただし、複雑なリンカールールを回避するために、C ++ではすべてのオブジェクトに一意の定義が必要です。C ++がオブジェクトとしてメモリに格納する必要があるエンティティのクラス内定義を許可した場合、そのルールは破られます。

const変数は、クラス内で宣言する必要があるが、それはそれで定義することはできません。クラスの外でconst変数を定義する必要があります。

T1() : t( 100 ){}

ここではt = 100、クラスの初期化が発生するずっと前に、初期化リストで割り当てが行われます。


3
最後のステートメントについて少し詳しく説明してもらえますかHere the i = 10 assignment in initializer list happens much before the class initilizaiton occurs.。そして基本的に、そのようなクラス内での定義を許可することは、コンパイラ固有の権利ですか?
チャイタンヤ2013年

3
i = 10の割り当てとは?
Daniel Daranas 2013年

上記の方法で初期化するクラスに定数があります。ただし、そのクラスのオブジェクトを作成しようとするとoperator = function not found、VC ++ でそれを示すエラーが表示されます。何が問題なのでしょうか?
Rohit Shinde 2014年

4
帰属のない誰かの正確な言葉を使用する場合、それは盗作と呼ばれます。適切な帰属を使用してください-を参照してstroustrup.com/bs_faq2.html#in-classstackoverflow.com/questions/13662441/...
バンブー

ええ、私も答えのコードを完全に理解していません-それは一体何ですか?cppファイル実装に配置できますか?
トマーシュザト-モニカ

50

まあ、あなたはそれを作ることができますstatic

static const int t = 100;

または、メンバー初期化子を使用できます。

T1() : t(100)
{
    // Other constructor stuff here
}

2
彼の使用(および/または意図)については、静的にする方がはるかに良いでしょう。
Mark Garcia

@FredLarson一部のg ++​​バージョンではそのような初期化が許可されていないようですか?またはそれはまったく許可されていませんか?
Chaitanya 2013年

3
@Chaitanya:C ++ 11非静的メンバー初期化子はgcc 4.7から実装されています。
ジェシーグッド

@MarkGarciaなぜずっと良いの?const member関数/オブジェクトからアクセス可能である必要がある場合は、要件である可能性がありますが、なぜ静的ですか?
Asif Mushtaq 2016

静的の初心者に例を示すことは通常誤解を招きますが。それは、そのクラスのすべてのインスタンス(オブジェクト)に対して1つだけであることを知らない可能性があるためです。
Muhamed Cicak 2017

30

クラス内のconstメンバーを初期化する方法はいくつかあります。

一般にconstメンバーの定義には、変数の初期化も必要です。

1)クラス内で、constを初期化する場合、構文は次のようになります。

static const int a = 10; //at declaration

2)2番目の方法は

class A
{
  static const int a; //declaration
};

const int A::a = 10; //defining the static member outside the class

3)宣言時に初期化したくない場合は、もう1つはコンストラクタを介して変数を初期化する必要があります(コンストラクタの本体ではなく)。それはこのようでなければなりません

class A
{
  const int b;
  A(int c) : b(c) {} //const member initialized in initialization list
};

8
この回答には説明が必要だと思います。クラスメンバーにstaticキーワードを使用しても、コンパイラーを満足させる任意の構文は追加されません。これは、オブジェクトのすべてのインスタンスに対して、定数の有無にかかわらず、変数の単一のコピーがあることを意味します。これは慎重に検討する必要がある設計上の選択です。将来、プログラマーは、この一定のクラスメンバーが、指定されたオブジェクトの存続期間中は一定のままであるにもかかわらず、オブジェクトごとに異なる可能性があると判断することがあります。
オペトレンコ2014

同意する..staticを使用すると、すべてのオブジェクトに対してそのコピーが1つだけ作成されます。すべてのオブジェクトの単一コピーの場合、1と2が機能するはずです。各オブジェクトの個別コピーの場合、3が機能します
ravs2627

この回答は、影響のない単純な構文の変更を示唆していますが、静的に変更するのはそうではありません。
Isaac Woods、

doubleまたはfloatを使用する必要がある場合はどうなりますか?これはC ++ 11標準の一部ですか?
serup

14

constクラスのデータメンバーを静的にしたくない場合constは、クラスのコンストラクターを使用してデータメンバーを初期化できます。例えば:

class Example{
      const int x;
    public:
      Example(int n);
};

Example::Example(int n):x(n){
}

constクラスに複数のデータメンバーがある場合は、次の構文を使用してメンバーを初期化できます。

Example::Example(int n, int z):x(n),someOtherConstVariable(z){}

3
私は....これが受け入れられたものよりも良い答えを提供して考える
イアン・

1
非常に明確な例と、複数を示すバリエーションをありがとう!読者のあいまいさや余分なリサーチ/スクロールを排除しました!
クリアライト2018年

13
  1. C ++ 11をサポートするようにコンパイラをアップグレードすると、コードは完全に機能します。

  2. コンストラクターで初期化リストを使用します。

    T1() : t( 100 )
    {
    }

6

別の解決策は

class T1
{
    enum
    {
        t = 100
    };

    public:
    T1();
};

したがって、tは100に初期化され、変更できず、プライベートです。


3

メンバーが配列の場合、通常のメンバーよりも少し複雑になります。

class C
{
    static const int ARRAY[10];
 public:
    C() {}
};
const unsigned int C::ARRAY[10] = {0,1,2,3,4,5,6,7,8,9};

または

int* a = new int[N];
// fill a

class C {
  const std::vector<int> v;
public:
  C():v(a, a+N) {}
};

2

別の可能な方法は名前空間です:

#include <iostream>

namespace mySpace {
   static const int T = 100; 
}

using namespace std;

class T1
{
   public:
   T1()
   {
       cout << "T1 constructor: " << mySpace::T << endl;
   }
};

欠点は、他のクラスでもヘッダーファイルが含まれている場合に定数を使用できることです。


1

これは正しい方法です。このコードを試すことができます。

#include <iostream>

using namespace std;

class T1 {
    const int t;

    public:
        T1():t(100) {
            cout << "T1 constructor: " << t << endl;
        }
};

int main() {
    T1 obj;
    return 0;
}

使用している場合はC++10 Compiler or below、宣言時にconsメンバーを初期化できません。したがって、ここではconstデータメンバーを初期化するコンストラクターを作成する必要があります。またT1():t(100)、瞬時にメモリを取得するには、初期化リストを使用する必要があります。


0

staticこのクラスメンバー変数の初期化を可能にするために追加できます。

static const int i = 100;

ただし、クラス宣言内で使用されるすべてのオブジェクトは、インスタンス化されたオブジェクトのスコープメモリ外の内部メモリに格納されている同じ静的変数を共有するため、これは常にクラス宣言内で使用するのが良い方法ではありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.