Effective.C読書ノート04

1674 ワード

条項07:マルチステートベースクラスにvirtual構造関数を宣言する
class TimeKeeper
{
public :
	TimeKeeper();
	virtual ~TimeKeeper();
	...
};
class AtomicClock:public TimeKeeper{ ... };
TimeKeeper *ptk = getTimeKeeper();
delete ptk;
base宣言virtual構造関数.classにvirtual関数がある場合は、virtual構造関数を持つ必要があります.これにより、derived classesのメモリが正しく解放されます.
通常のclassesでvirtual構造関数を宣言する必要がない場合、メモリのオーバーヘッドが増加します.
心得:classに少なくとも1つのvirtual関数が含まれている場合にのみ、virtual構造関数を宣言します.
マルチステート性質を持つbase classesはvirtual構造関数を宣言するべきであることを覚えておいてください.classにvirtual関数がある場合は、virtual構造関数を持つ必要があります.
classesの設計目的はbase classesとして使用されない場合、または多態性を備えるためでない場合、virtual構造関数を宣言するべきではありません.
条項08:例外を構造関数から逃がさない
データベース接続を担当するclassがあるとします.
class DBConnection
{
	public DBConnection create();
	void close();
};

class DBConn   // class DBConnection 
{
public :
	...
	~DBConn()          // 
	{
		db.close();
	}
private:
	DBConnection db;
}
// 
DBConn::~DBConn()
{
	try{db.close();}
	catch()
	{
		// , close 
		std::abort();
	}
}
// 
DBConn::~DBConn()
{
	try{db.close();}
	catch()
	{
		// , close 
	}
}
// 

少し良い方法は:
class DBConn
{
public:
	...
	void close()           // 
	{
		db.close();
		closed = true;
	}
	~DBConn()
	{
		if(!closed)
		{
			try                 // ( )
			{
			    db.close();
			}
			catch (...)          // 
			{
				 , close  // 
                ...
			}


		}
	}
private:
	DBConnection db;
	bool closed;

};

closeを呼び出す責任をDBConn解析関数の手からDBConnクライアントの手に移す.
解析関数は決して例外を吐かないでください.解析関数によって呼び出された関数が例外を投げ出す可能性がある場合は、解析関数は例外をキャプチャし、(伝播しない)プログラムまたは終了プログラムを飲み込む必要があります.
お客様が操作関数の実行中に放出された例外に反応する必要がある場合は、classは、構造関数ではなく一般的な関数を提供して操作を実行する必要があります.