20章 constメンバ変数の初期化

http://www.geocities.jp/ky_webid/cpp/language/020.html

C++のconstには状況よって様々な効果があるので少しややこしいです。

とりあえずひとつずつ理解していきたいと思います。

まずはC言語的なconstについてですが、これは単にその変数、もしくはその変数が参照している値を変更不可にすることができます。

const int i = 100;  // iの値を変更できない
int* const p;       // pの値を変更できない
const int* p;       // pが指している値を変更できない
const int* const p; // pの値を変更できなくて且つ指してる値も変更できない

C++ではこれ以外にconstの役割がかなり増えました。

ひとつずついきましょう。

まずはメンバイニシャライザについてです。

メンバ変数にconstを適応した場合、どこかで初期値を与えないといけません。

クラスを宣言した時にはまだメンバ変数は存在していないので、実際にインスタンス化するときに初期値を与えることになるわけなんですが、コンストラクタ内で初期値を渡そうとしてもうまくいきません。

using namespace std;

class CSample {
public:
    const int m_num;
    CSample();
};

CSample::CSample () {
    m_num = 100;
}
$ cl /W4 /EHsc main.cpp
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp
main.cpp(8) : warning C4512: 'CSample' : 代入演算子を生成できません。
        main.cpp(4) : 'CSample' の宣言を確認してください。
main.cpp(10) : error C2758: 'CSample::m_num' : オブジェクト コンストラクタの初期化子リストで初期化されませんでした。
        main.cpp(6) : 'CSample::m_num' の宣言を確認してください。
main.cpp(11) : error C2166: 左辺値は const オブジェクトに指定されています。

コンパイルエラーとなります。

constが付いているので代入はできないのです。

じゃあどうやって初期値を与えるのか?

実は前にオーバーロードの章で少し習っています。

初期化をするためコンストラクタを呼んであれげれば良いのです。

#include <iostream>
using namespace std;

class CSample {
public:
    const int m_num;
    CSample();
};

CSample::CSample () : m_num(100) {
}

int main() {
    CSample obj;
    cout << obj.m_num << endl;
    return 0;
}
$ main
100

上記のようにコンストラクタ時にm_numのコンストラクタを呼ぶことで初期値の代入を可能としています。

もちろん複数のconstメンバ変数の初期値を代入することもできます。

また、コンストラクタに与えられた値を元に、constメンバ変数の初期化を行うこともできます。

#include <iostream>
using namespace std;

class CSample {
public:
    const int m_num1;
    const int m_num2;
    CSample(int num);
};

CSample::CSample (int num) : m_num1(num), m_num2(num*2) {
}

int main() {
    CSample obj(200);
    cout << obj.m_num1 << endl;
    cout << obj.m_num2 << endl;
    return 0;
}
$ main
200
400

複数のコンストラクタを呼ぶ場合にはカンマ区切になるので注意が必要ですね。