名前付きコンストラクタ
いわゆる名前付きコンストラクター( https://isocpp.org/wiki/faq/ctors#named-ctor-idiomも参照) を使用して、コンストラクターを作成できprivate
ます。
class RenderTarget {
private:
RenderTarget (int w, int h) :
width_(w), height_(h), buffer_(w*h)
{
// NOTE: Error checking completely removed.
}
public:
static RenderTarget create(int width, int height) {
// Constraint Checking
if (width<0 || height<0)
throw std::logic_error("Crizzle id boom shackalack");
return RenderTarget(width, height);
}
名前付きコンストラクターは、温度 <-- 摂氏 |など、使用するのが曖昧な複数のコンストラクターがある場合に役立ちます。華氏 | ケルビンまたは距離 <-- メートル | ヤード | キュービット | キロメートル | ... .
そうでなければ、(個人的な意見ですが)予期せぬ抽象化と注意散漫をもたらすので、避けるべきです。
三項演算子とthrow
C++ では、[expr.cond]throw
で、三項演算子 ( ?:
-operator)の一方または両方のオペランドで -expressionsを使用できます。
RenderTarget(int w, int h) :
width_(w<0 ? throw std::logic_error("Crizzle id boom shackalack") : w),
height_(h<0 ? throw std::logic_error("Crizzle id boom shackalack") : h),
surface_(w*h)
{}
引数を保存しない場合は?:
、もちろん式の中で使用することもできます:
RenderTarget(int w, int h) :
surface_(
(w<0 ? throw std::logic_error("Crizzle id boom shackalack") : w)
* (h<0 ? throw std::logic_error("Crizzle id boom shackalack") : h)
)
{}
または、前提条件チェックを 1 つのオペランドに結合します。
RenderTarget(int w, int h) :
surface_(
(w<0||h<0) ? throw std::logic_error("Crizzle id boom shackalack") :
w * h
)
{}
-expression inline?:
で -operator を使用すると、基本的な制約チェックに非常に便利であり、デフォルトのコンストラクター (存在する場合) を使用して、コンストラクター本体内で「実際の初期化」を行う必要がなくなります。throw
これは、より複雑なシナリオでは少し扱いにくくなる可能性があります。
静的プライベート メンバー
もちろん、両方の長所を活用できます。
private:
static bool check_preconditions(int width, int height) {
if (width<0 || height<0)
return false;
return true;
}
public:
RenderTarget(int w, int h) :
surface_(
check_preconditions(w,h) ?
w*h :
throw std::logic_error("Crizzle id boom shackalack")
)
{}
...または、事前条件チェックが必要なメンバーの静的関数を作成します。
private:
static Buffer create_surface(int width, int height) {
if (width<0 || height<0)
throw std::logic_error("Crizzle id boom shackalack")
return Buffer(width*height);
}
public:
RenderTarget(int w, int h) :
surface_(create_surface(w, h))
{}
これは、制約チェック用の完全な C++ 機構が手元にあり、たとえばロギングを簡単に追加できるため、便利です。これは適切にスケーリングされますが、単純なシナリオではあまり便利ではありません。