コンストラクタとデストラクタ


コンストラクタ

コンストラクタはクラスで宣言、定義ができる特殊なメンバ関数で、
クラスを変数として宣言した時(メモリ上に作成される時)に
自動的に呼び出されます。

コンストラクタの役割

コンストラクタはクラスを生成した際に呼び出される関数なので、
この関数で行う役割はメンバ変数の初期化が主な役割になります。
コンストラクタでメンバ変数の初期化を行い、
すぐに使用できる状態にすれば、使い勝手がよくなるので
プログラミングの効率が良くなります。

コンストラクタの書式

以下がコンストラクタの書式です。

// 宣言
クラス名();

// 定義
クラス名::クラス名()
{
}

// 具体例
class Employee
{
public:
	// コンストラクタ
	Employee();
private:
	int Number;
};

Employee::Employee() 
{
	Number = 0;
}

コンストラクタは「関数名」と「関数定義」に
通常の関数とは異なる特徴があります。

関数名

コンストラクタの関数名は「定義しているクラス名」になります。
例えばEmployeeというクラス名だったら、Employee、
PlayerだったらPlayerが関数名になります。

関数定義

関数の基本的な書式は「戻り値の型 クラス名::関数名(引数)」ですが、
コンストラクタの書式は「クラス名::関数名(引数)」となっており、戻り値の型は不要です。

デフォルトコンストラクタ

デフォルトコンストラクタとは引数が存在しないコンストラクタのことです。
自作デフォルトコンストラクタの定義は開発者が決めることができますが、
もし、実装しなかったとしてもコンパイラが暗黙的に実装しています。
実行時も変数宣言や動的確保の際に「()」を記述して明示的に実行させることもできますが、
「()」を指定していない場合でも暗黙的に実行されています。

class Employee
{
public:
	// デフォルトコンストラクタ
	Employee();

	int Number;
};

Employee::Employee()
{
	Number = 1001;
}

void main(void)
{
	Employee suzuki;

	printf("Number = %d\n", suzuki.m_Number);
}

実行結果:
	Number = 1001

上のコードの結果ら分かるようにsuzukiという変数を宣言した際に
「()」の指定はしていませんが、デフォルトコンストラクタは暗黙的で実行されます。

オーバーロード

コンストラクタはオーバーロードの機能を使用して
複数のコンストラクタを作成することができます。
これによって状況に応じたクラスの作成が可能となります。

class Employee
{
public:
	// コンストラクタその1(引数なし)
	Employee(void);
	// コンストラクタその2(初期化パラメータ有)
	Employee(int num, char *name, int salary);
	void ShowInfo(void);

private:
	int Number;
	char Name[32];
	int Salary;
};

Employee::Employee(void)
{
	m_Number = 1001;
	strcpy_s(m_Name, "山田太郎");
	m_Salary = 220000;
}

Employee::Employee(int num, char *name, int salary)
{
	m_Number = num;
	strcpy_s(m_Name, name);
	m_Salary = salary;
}

void Employee::ShowInfo(void)
{
	printf("社員番号 = %d\n", m_Number);
	printf("名前 = %s\n", m_Name);
	printf("給料 = %d\n", m_Salary);
}

void main(void)
{
	Employee yamada;
	Employee sato(1002, "佐藤一郎", 200000);

	yamada.ShowInfo();
	printf("\n");
	sato.ShowInfo();
}

実行結果:
	社員番号 = 1001
	名前 = 山田太郎
	給料 = 220000
			
	社員番号 = 1002
	名前 = 佐藤一郎
	給料 = 200000

デストラクタ

デストラクタはクラスが破棄される際に自動で呼び出される特殊なメンバ関数です。
クラスを破棄するタイミングは主に以下の3つが考えられます。
	
プログラム終了
変数の寿命が尽きた
new作成した動的なクラスをdeleteで破棄する

デストラクタの役割

デストラクタの役割は終了時に呼び出されることから
メンバ変数の後始末が主な役割になります。
メンバ変数の後始末といってもintやfloatなどの通常の変数は
そのままメモリが解放されるだけなので問題はないのですが、
ポインタ変数をメンバに持っている場合は適切な解放処理を行う必要があります。

デストラクタの書式

以下がデストラクタの書式です。

// 宣言
~クラス名();

// 定義
クラス名::~クラス名()
{

}

// 具体例
class Employee
{
public:
	// コンストラクタ
	Employee();

	// デストラクタ
	~Employee();

private:
	int* Number;
};

Employee::Employee()
{
	Number = new int;
}

Employee::~Employee()
{
	delete(Number);
}


コンストラクタは「関数名」「アクセス範囲指定」「関数定義」
「オーバーロード設定」に通常の関数とは異なる特徴があります。

関数名

デストラクタの関数名は定義しているクラス名に~(チルダ)をつけます。
例えばEmployeeというクラス名だったら、~Employee、
Animalだったら~Animalが関数名になります。

アクセス範囲指定

デストラクタは必ずpublicのアクセス範囲に定義する必要があります。
privateやprotectedではエラーになるので気をつけてください。

デストラクタの定義

デストラクタの定義もコンストラクタと同じで
「クラス名::~関数名(引数)」なので、戻り値の型が不要です。

オーバーロード不可

デストラクタはコンストラクタと違い引数を追加して
オーバーロードで呼び出すことができません。