問題の紹介
以下のコードを読んでください。
class Time
{
public:
Time(int hour, int min, int sec)
{
_hour = hour;
_min = min;
_sec = sec;
}
private:
int _hour;
int _min;
int _sec;
};
オブジェクトをインスタンス化した後、オブジェクトは自動的にコンストラクターを呼び出して自身の値を初期化し、初期化作業を完了します。ただし、それをメンバー変数の初期化とは言えません,初期化は一度しかできませんが、「初期化」は関数本体内で動作するため、正確には複数回代入することができます。, したがって、関数本体の代入を初期化とみなすのは偏っています。
したがって、初期化子リストの導入です
1 初期化リスト
構文: コロンで始まり、その後にデータ メンバーのカンマ区切りのリストが続き、各「メンバー変数」の後に括弧で囲まれた初期値または式が続きます。
具体的な形式は次のとおりです。
class Time
{
public:
Time(int hour, int min, int sec)
: _hour(hour)
, _min(min)
, _sec(sec)
{
}
private:
int _hour;
int _min;
int _sec;
};
2 注意事項
オブジェクトが初期化されると、初期化リストに従ってメンバー変数が初期化され (カスタム型がある場合は、対応するデフォルトのコンストラクターが呼び出されます)、関数本体の内容が実行されます。C++ は、初期化リストに基づいてメンバー変数を初期化する方法を認識しています。初期化リストが表示されない場合、関数はデフォルトで対応する初期化リストを生成します。
- 各メンバー変数は、初期化リストに 1 回だけ出現できます (初期化は 1 回だけ出現できます)。
- クラスには参照メンバー変数、const メンバー変数、およびカスタム型メンバー (クラスにデフォルトのコンストラクターがない場合) が含まれており、これらを初期化のために初期化リストに配置する必要があります。
- クラス内でメンバー変数が宣言される順序は、初期化リスト内の順序に関係なく、初期化リスト内で初期化される順序になります。
1~3
- 初期化子リストの各メンバー変数しかできない1 回だけ発生します (初期化は 1 回だけ発生します)。
- クラスに含まれるもの参照メンバー変数、const メンバー変数、カスタム型メンバー (およびクラスにデフォルトのコンストラクターがない場合)、初期化子リストに配置して初期化する必要があります。
カスタム型を初期化する場合は、まずその型のデフォルト コンストラクターがあることを確認する必要があります (デフォルト コンストラクターが何であるかに注意してください)。そうでない場合は、現在のクラスに対応するコンストラクターがないため、エラーが報告されます。コンストラクターを指定すると、コンパイラーはクラス関数のデフォルトのコンストラクターを呼び出して実行します。コードは以下のように表示されます。
カスタムタイプの場合
class Date
{
public:
// 重点在构造函数,其他不是重点
// 全缺省才是默认构造函数
//Date(int year=0, int month=0, int day=0)
//{
// _year = year;
// _month = month;
// _day = day;
//}
Date& operator=(const Date& d1)
{
_year = d1._year;
_month = d1._month;
_day = d1._day;
return *this;
}
private:
int _year;
int _month;
int _day;
};
class Time
{
public:
Time(int hour=0, int min=0, int sec=0)
: _hour(hour)
, _min(min)
, _sec(sec)
{
//在函数体初始化,比较麻烦,必须保证存在默认构造z函数
Date t1;
_d = t1;
}
private:
int _hour;
int _min;
int _sec;
Date _d;
};
int main()
{
Time t(6, 30, 30);
return 0;
}
Date クラスのデフォルトのコンストラクターが表示されない場合、コンパイラーはランダムな値である _d の値を初期化しません。逆に、初期化リストに初期化作業を記述しておけば、Date クラスにデフォルトのコンストラクタが表示されていなくても、コンパイラは _d のカスタム型を 0 に初期化します。
class Date
{
public:
Date& operator=(const Date& d1)
{
_year = d1._year;
_month = d1._month;
_day = d1._day;
return *this;
}
private:
int _year;
int _month;
int _day;
};
class Time
{
public:
Time(int hour = 0, int min = 0, int sec = 0)
: _hour(hour)
, _min(min)
, _sec(sec)
,_d()
{
}
private:
int _hour;
int _min;
int _sec;
Date _d;
};
int main()
{
Time t(6, 30, 30);
return 0;
}
const 型の場合、
const 変更されたメンバー変数は定数ですが、定数は変更できないため、関数本体で代入できません。ただし、リスト内で初期化することも、C++11 の機能を使用して宣言時に値を割り当てることもできます。
参照型:
参照型の場合、参照は定義時に初期化する必要があり、再割り当てできないため、初期化リストにも記述する必要があります。
こちらのブログで詳しく解説していますので、ぜひご参照ください。
- クラス内でメンバー変数が宣言される順序は、初期化リスト内の順序に関係なく、初期化リスト内で初期化される順序になります。