Non-virtual Interface idiome (NVI) はかなり自明です:public virtual
関数を書くのではなく、次のように実装関数public
を呼び出す関数を記述します。private virtual
class Object{
virtual void v_load();
public:
void load(){ v_load(); }
}
これにより、基本クラスの作成者は、事前条件と事後条件をチェックして適用したり、他の関数を適用したりして、派生クラスの作成者がそれらを忘れないようにすることができます。
あなたが派生作成者である場合、基本クラスを自分で書きたいと思うかもしれません - それを呼びましょうPawn
- それは の機能を拡張するload()
ため、オーバーライドする必要がありますv_load()
。しかし今、あなたは問題に直面しています:
をオーバーライドv_load()
すると、クラスから派生したい他のクライアントは常にその動作を上書きしPawn::v_load()
、private
関数であるため呼び出すことも、もちろん無限ループにつながるようにPawn::load()
定義されているため呼び出すこと{ v_load; }
もできませんObject
. さらに、そうするように要求すると、その呼び出しを忘れたときにミスが発生する可能性があります。それを有効にしたい場合は、へのアクセスを のように指定する必要v_load()
がprotected
ありObject
ますObject
。
v_load()
もちろん、新しい関数を呼び出すためにオーバーライドすることもできますv_pawnLoad()
。これはクライアントによってオーバーライドされますが、多くのクライアントが間違った関数をオーバーロードする可能性があるため、エラーが発生しやすいようです。
では、前提条件をチェックしたり、他の関数を呼び出したり、(可能であれば) 有効にせずに、クライアントに要求したり、基本実装を呼び出したりする機能を維持しながらPawn
、クライアントがオーバーライドできるように設計するにはどうすればよいでしょうか?v_load()
Object
Pawn
v_load()