これを を使用したくない知的な演習として扱うにはstd::vector
、クラスを分割して、単一の責任を持つようにする必要があります。これが私の「整数配列」クラスです。その責任は、整数配列のメモリを管理することです。
class IntArray {
public:
IntArray() : ptr_(new int[100]) {}
~IntArray() { delete[] ptr_; }
IntArray(const IntArray&) = delete; // making copyable == exercise for reader
IntArray& operator=(const IntArray&) = delete;
// TODO: accessor?
private:
int* ptr_;
};
これが私のファイル処理クラスです。その責任は、を管理することFILE*
です。
class FileHandle {
public:
FileHandle(const char* name, const char* mode)
: fp_(fopen(name, mode))
{
if (fp_ == 0)
throw std::runtime_error("Failed to open file");
}
~FileHandle() {
fclose(fp_); // squelch errors
}
FileHandle(const FileHandle&) = delete;
FileHandle& operator=(const FileHandle&) = delete;
// TODO: accessor?
private:
FILE* fp_;
};
構築エラーを例外に変換することに注意してください。fp_
有効なファイル ポインターであることは維持したい不変条件であるため、この不変条件を設定できない場合は構築を中止します。
これで、File_ptr
例外を安全にするのは簡単になり、クラスは複雑なリソース管理を必要としなくなりました。
class File_ptr {
private:
FileHandle p;
IntArray i;
public:
File_ptr(const char* n, const char* s)
: p(n, s)
, i()
{}
};
ユーザー宣言のデストラクタ、コピー代入演算子、またはコピー コンストラクタがないことに注意してください。メンバーの順序を入れ替えることができます。どちらの場合でも、どのコンストラクターがスローするかは問題ではありません。