C++ オブジェクトの生存期間を使ったデストラクタで後処理を行う方法

 

hissatu01やりたいコト

デストラクタを実装している言語で有効な書き方です。
オブジェクトの生存期間を使ったデストラクタで後処理を行う方法を書きます。

やり方

やり方は簡単で、後処理用のクラスを作って、デストラクタにやりたい後処理を定義します。
後はこの後処理クラスを後処理したい場所に書いて、オブジェクトの生存期間が終わった時に自動的に後処理が行われるように記述します。
(文章だとちんぷんかんぷんですね…)
単純ですが、結構コードが見やすくなるので、私はこの書き方が好きです。

改善前

例えば、下のようにうるう年の計算中はDriverのflagをfalseにして、
何かの処理を停止しなければならない。
加えて、うるう年の計算が終わったらDriverのflagを戻して何かの処理を復帰しないといけない。

こんなときにこんな書き方しませんか?

class Driver
{
public:
	bool flag = true;
};

void DispUrudoshi(int year, Driver *pDriver)
{
	pDriver->flag = false;

	if (year % 4 != 0){
		cout << year << "はうるう年じゃない" << endl;
		pDriver->flag = true;
		return;
	}
	if (year % 100 != 0){
		cout << year << "はうるう年です" << endl;
		pDriver->flag = true;
		return;
	}
	if (year % 400 == 0){
		cout << year << "はうるう年です" << endl;
		pDriver->flag = true;
		return;
	}
	else{
		cout << year << "はうるう年じゃない" << endl;
		pDriver->flag = true;
		return;
	}
	pDriver->flag = true;
}

フラグ管理のコードがうっとうしいですね。
これがポインタの管理や、IOまわりのopen / closeだと、もっとひどいことになりますね。

改善後

今度は、「後処理用のクラスを作って、デストラクタにやりたい後処理を定義」してみます。

class Driver
{
public:
	bool flag = true;
};

// 後処理用のクラス
class FlagManager
{
private:
	Driver *_pDriver;
public:
	FlagManager(Driver *pDriver){
		_pDriver = pDriver;
		pDriver->flag = false;
	};
	~FlagManager(){
		// デストラクタにやりたい後処理
		_pDriver->flag = true;
	};
};

void DispUrudoshi(int year, Driver *pDriver)
{
	// 後処理クラスのオブジェクトを作成
	// スコープを抜けると勝手に後処理が実行される
	FlagManager fm(pDriver);

	if (year % 4 != 0){
		cout << year << "はうるう年じゃない" << endl;
		return;
	}
	if (year % 100 != 0){
		cout << year << "はうるう年です" << endl;
		return;
	}
	if (year % 400 == 0){
		cout << year << "はうるう年です" << endl;
		return;
	}
	else{
		cout << year << "はうるう年じゃない" << endl;
		return;
	}
}

これで、すっきりですね。

最後に

今回は小技ですいません。
デストラクタってメンバ変数の解放に使うくらいしか用が無いと思われがちですが、
生存期間を使った面白い実装をご紹介しました。
デストラクタの可能性を感じてもらえたら幸いです。

 

※2016/03/23 お客さんから、「C#でもできるっぽいこと書いてあるけど、C#のデストラクタはガベコレに管理されているのでできないよ」と指摘をいただきタイトルと文章修正。
※2016/02/03 関数名をIsUrudoshiからDispUrudoshiに変更

Follow me!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です