NVI イディオムを使用して次の階層があるとします。
class Base
{
public:
virtual ~Base() {}
void foo() { cout << "Base::foo" << endl; foo_impl(); }
private:
virtual void foo_impl() = 0;
};
class A : public Base
{
private:
virtual void foo_impl() { cout << "A::foo_impl" << endl; }
};
階層のある時点で、非仮想基本メソッドに不変条件を「追加」したい場合、最善の方法は何ですか?
1 つの方法は、SpecialBase レベルで NVI イディオムを再帰することです。
class SpecialBase : public Base
{
private:
void foo_impl() { cout << "SpecialBase::foo" << endl; bar_impl(); }
virtual void bar_impl() = 0;
};
class B : public SpecialBase
{
private:
virtual void bar_impl() { cout << "B::bar_impl" << endl; }
};
しかし、階層に追加する派生ベースごとに (異なる名前の) メソッドを追加したくないので、このアイデアはあまり好きではありません...
別の方法は、次のものを用意することです (これは NVI ではありません)。
class Base
{
public:
virtual ~Base() {}
virtual void foo() { base_foo(); foo_impl(); }
protected:
void base_foo() { cout << "Base::foo" << endl; }
virtual void foo_impl() = 0;
};
class SpecialBase : public Base
{
public:
virtual void foo() { base_foo(); specialbase_foo(); foo_impl(); }
protected:
void specialbase_foo() { cout << "SpecialBase::foo" << endl; }
};
class B : public SpecialBase
{
private:
virtual void foo_impl() { cout << "B::foo_impl" << endl; }
};
私の意見では、具象クラスはいつでも仮想メソッドを実装する必要があるだけなので、混乱は少ないと思いますが、派生基本クラスも選択した場合は基本 (仮想) メソッドをオーバーライドできます。
同じことを達成するための別のよりクリーンな方法はありますか?
編集:
次のような階層を持つことができる非常に一般的な設計パターンを探しています。
Base <- A
<- B
<- SpecialBase <- C
<- D
<- VerySpecialBase <- E
<- StrangeBase <- F
各Base
クラスは foo をオーバーライドできますが、クラスA-F
は再実装するだけで済みますfoo_impl
。
別のオプションのカスタマイズ仮想関数 (例: bar_impl
) を追加するだけでは、ここでは役に立たないことに注意してください。