C++ ⇒ VBA 書いて覚えるための初心者自己中記事

C++ ⇒ VBA 勉強の履歴を付けるというかノート代わりに使ってます

C++ 共用体 書いて覚えるための初心者自己中記事

メンバ変数が複数あるクラスで、状況によって使い分けるので常に1メンバ変数しか使用しない。という場合に、メモリ領域が無駄にならないようにする方法。

共用体という機能を使うと、複数のメンバ変数に対してメモリ領域は共有になる。

使い方は構造体の宣言と似ていて、struct を union にするだけ。

 

union test {
	int n;
	double d;
};

使用するメモリ領域の大きいほうにサイズでアドレスが確保される。

 

union以外の部分が・・・。

まず、

class Number {
private:
	enum Type {
		INT, DOUBLE
	};
private:
	union Value {
		int int_;
		double double_;
	};
	Value m_value;//保存している値
	Type m_type;//保存している値の型情報
};

クラスNumber

enum でINT と DOUBLEを登録

union でint型メンバ変数をdouble型メンバ変数を共用体で用意

共用体は型らしいので実際にはその下で共用体Value型のメンバ変数m_valueを用意。

後は保存している型がどちらなのか分かるようにする変数、こちらもenumで作ったType型の変数で用意。

 

次、

void operator=(int n);
void operator= (double n);
void Number::operator=(int n) {
	m_value.int_ = n;
	m_type = INT;
}
void Number::operator=(double n) {
	m_value.double_ = n;
	m_type = DOUBLE;
}

代入演算子オーバーロードのプロトタイプと実装部分。

代入された値の型によって動作を変えている。

次、

Number(int n = 0) { operator=(n); }
Number(double n) { operator=(n); }

コンストラクタも型によって分けている。

それぞれが、先ほどの代入演算子オーバーロードを使うようになっている。

 

次、

friend ostream& operator<<(ostream& ostr, const Number& n);
ostream& operator<<(ostream& ostr, const Number& n) {
	if (n.m_type == Number::INT) {
		return ostr << "INT(" << n.m_value.int_ << ')';
	}
	else {
		assert(n.m_type == Number::DOUBLE);
		return ostr << "DOUBLE(" << n.m_value.double_ << ')';
	}
}

プロトタイプと実装部。

実装部かと思ったら、違った、いや実装なんだけど。

実装部はクラス外にある。

でこのオーバーロードはなんだ?

俺がcoutをちゃんと理解できていないということなのか?

<<

これ挿入演算子というのか・・。

cout に挿入演算子で何か変数とかか。

この挿入演算子オーバーロードではNumber型の変数が来たら特定の動作をするってことね。それだけか。

 

共用体は継承できない。

 

別の使い方。

#define ARRAY_SIZE(array) (sizeof (array) / sizeof *(array))
 
union Int {
	int value;
	unsigned char bytes[sizeof(int)];
};
 
void Show(const unsigned char* bytes, int size) {
	for (int i = 0; i < size; ++i) {
		printf("%02X ", bytes[i]);
	}
	puts("");
}
 
int main() {
	Int n;
	n.value = 0x89ABCDEF;
	Show(n.bytes, ARRAY_SIZE(n.bytes));
	system("pause");
}

これも凄い。

片方に入れてもう片方で使ってる。

 

共用体のメンバ変数を初期化する場合は最初のメンバ変数じゃないと初期化されないらしい。

あと初期化の方法が配列みたい。

Int n = { 0x89ABCDEF };

最初のメンバ変数って記述した順番って意味であってるかな。

 

ここまで。