テンプレートでデザインパターンの Template Method を実装する方法。
template<class T>
class Base
{
public:
void Run() { static_cast<T*>(this)->Foo(); }
protected:
void Foo() { std::cout << "Base Foo()" << std::endl; }
};
class Inherit : public Base<Inherit>
{
protected:
void Foo() { std::cout << "Inherit Foo()" << std::endl; }
};
void main()
{
Base<Inherit> base;
base.Run();
}
継承元のクラスは継承先のクラスをテンプレートの引数として取ることによって、継承先のクラスを呼び出すことが出来ます。
virtual になってないので呼び出しのコストが少ないせいか、速度を重視する ATL ではこのテクニックが多用されています。
↑のプログラムはオーバーライドをしなくても Base::Foo() が呼び出されるようになっていますが、Base::Foo() を消せば、オーバーライドしていない場合はコンパイルエラーになります。
そして恐ろしいのが、これは static メソッドにも対応できるってことですね。
template<class T>
class Base
{
public:
void Run() { T::Foo(); }
protected:
static void Foo() { std::cout << "static Base Foo()" << std::endl; }
};
class Inherit : public Base<Inherit>
{
protected:
static void Foo() { std::cout << "static Inherit Foo()" << std::endl; }
};
void main()
{
Base<Inherit> base;
base.Run();
}
うーん、テンプレートの変態っぷりが楽しいw