Cpp 構造体 クラスの初期化

提供:yonewiki
2024年1月25日 (木) 21:10時点におけるYo-net (トーク | 投稿記録)による版 (→‎構造体 クラスの初期化)

C++に戻る


本来の表記は「C++(Cpp) 構造体 クラスの初期化」です。この記事に付けられた題名はテンプレート:記事名の制約から不正確なものとなっています。

※このページではC++にのみ存在する機能として、記事タイトルがC++ 構造体 クラスの初期化になっています。

構造体 クラスの初期化

 あんまり知られていないやり方かもしれませんが、C++では構造体やクラスを定義した時にメンバ変数の後ろに「:」(コロン)を付けて初期化することが出来ます。クラスについてはこの先で説明するので、クラスを一通り勉強してから戻ってきてもいいですね。こういうときの構文としての名前がついているのかと思ったんですけど、あまりはっきりとはしていません。強いて言うならば、メンバ初期化子リスト : (コロン記号の意味として)という名前なのかなと思います。

 使い方のサンプルとしては

Sample.h

struct Sample{
    int iValue : 10;
    CSampleClass objCSampleClass : objCSampleInitClass;
}

CExample objCExample : objCExampleInitValue;

 構造体の方はなんとなく理解しやすい記述に見えると思いますが、最後の1行での使い方だとなんじゃこれ?って思いやすいです。これも初期値設定です。

 単純な使い方の場合は以下のように = を使った記述の方が分かりやすいかもしれません。

Sample.h

struct Sample{
    int iValue = 10;
    CSampleClass CSampleClass = objCSampleInitClass;
}

CExample objCExample = objCExampleInitValue;

 初期化と代入を明確に切り分けたい場合に : メンバ初期化子リストを使うのかもしれない。と、思ってみたり。


 ここで、この記事はおしまいと思いきや、まだ続きがあります。


 更にややこしいと感じさせながらも便利な記述方法も存在しています。例えば以下のように


Sample2.h FFFTPのプログラムを参考にしたサンプルです。

class Sample {
	const wchar_t* keyName;
	const wchar_t* name;
	int id;
	Sample(const wchar_t* keyName, const wchar_t* name, int id) noexcept : keyName{ keyName }, name{ name }, id{ id } {}
public:
	static Sound Connected;
	static Sound Transferred;
	static Sound Error;
	void Play() noexcept { PlaySoundW(keyName, 0, SND_ASYNC | SND_NODEFAULT | SND_APPLICATION); }
	static void Register();
};

 インライン(inline宣言を省略)にしたSampleコンストラクタのようにして : keyName{ keyName }, name{ name }, id{ id } とメンバ初期化子リストを記述できます。KeyName {(波カッコの始まり、オープン ブレース) keyName }(波カッコの終わり、クローズ ブレース)でひとカタマリです。このサンプルでは、3変数をカンマ区切りで、初期化しています。つまり、複数変数の初期化はカンマで区切るということです。波カッコの始まりの手前のKeyNameはクラスの中でのメンバ変数名で、波カッコ始まりの後ろと波カッコ終わりに囲まれたKeyNameは初期化引数として受け取る値の名前を意味しています。メンバ変数での名前と引数として受け取る名前のように役割は違うので、同じ変数名を使えます。コンストラクタ関数のメンバ初期化子リストについて説明していますが、メンバ関数に対しても同様です。


 文の末尾、最後の {} はプログラム本体を記述している部分として書いた {} のような何も中身のないコンストラクタとしてのプログラム関数という意味です。あしからず。


 更にメンバ初期化子リストは


  • : keyName{ keyName }, name{ name }, id{ id } { //コンストラクタプログラムコード記述位置 }
  • : keyName( keyName ), name( name ), id( id ) { //コンストラクタプログラムコード記述位置 }
  • : keyName = keyName, name = name, id = id { //コンストラクタプログラムコード記述位置 }


 のように書き換えることができますが、一番最初の波カッコで記述した場合だけ、集積体初期化という機能をもつことが出来ます。例えば、初期化の記述が以下のようにできるようになり、Soundクラスの変数を定義する際に


Sound Sound::Connected{ L"Connected_KeyNeme", L"Connected_name", 9000 };


 コンストラクタによる初期化値を付与する場合の記述では、上記にように配列要素みたいに記述ができるようになります。ConnectedというSoundクラスの中のSoundクラス型のメンバ変数は、アクセス指定子がpublicで静的メンバ変数を示すstaticなので、グローバル領域からSound::Connectedでアクセスできますので、上記の命令文はグローバル領域で記述できる宣言になります。グローバル領域にSound型クラスを静的メンバ変数Sound::Connectedの初期化を行うときの記述ですね。


 プログラムコードを持たないコンストラクタとメンバ関数Play()はインライン関数として宣言されていて、noexceptというキーワードがつけられています。noexceptは関数内で例外処理が発生しないことを示すキーワードです。


 PlaySoundWはWinAPIのひとつです。音を再生する処理を行うもので、KeyNameに設定したファイルパスの音や、Registryで設定した音を鳴らす仕組みです。今回の場合は、3つめの引数にレジストリ設定から鳴らすためのフラグが設定されているので、レジストリの設定に基づいて、音を鳴らしますが、具体的な処理の紹介についてはしません。この関数とレジストリに記述した仕組みを使うんだなと思っておいてもらえればよいと思います。また機会があれば紹介したいと思います。PlaySoundWというキーワードにリンクがついたら、紹介記事が出来たんだなと考えることができるでしょう。とおい未来の話ですね。


 

C++に戻る