그동안 개발하면서 template method pattern을 즐겨 사용하고 있는데, virtual 함수를 이용하여 구현했었다. 그런데 CRTP 를 이용해도 비슷한(동일한건 아님) 처리가 가능하다.
예를 들어 다음처럼 template method pattern 구현을 한경우,
#include <iostream> #include <memory> #include <vector> template<typename T, typename... Args> std::unique_ptr<T> make_unique(Args&&... args) { return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); } class Base { public: virtual ~Base() {} void DoWork() { DoBasicWork(); DoSpecialWork(); } void DoBasicWork(){ std::cout << "Do Basic work..\n"; } virtual void DoSpecialWork() = 0; }; class Derived1 : public Base { public: void DoSpecialWork() override { std::cout << "Do derived 1's special work..\n"; } }; class Derived2 : public Base { public: void DoSpecialWork() override { std::cout << "Do derived 2's special work..\n"; } }; int main() { std::vector<std::unique_ptr<Base>> vec_base; vec_base.push_back(make_unique<Derived1>()); vec_base.push_back(make_unique<Derived2>()); for(auto it = vec_base.begin(); it != vec_base.end(); ++it){ (*it)->DoWork(); } return 0; } |
CRTP 를 이용해서 (비슷하게) 다시 구현하면 다음과 같다. 동적 다형성(dynamic polymorphism)을 희생한 경우이다.
//.... 생략 .... template<typename Derived> class Base { public: virtual ~Base() {} void DoWork() { DoBasicWork(); static_cast<Derived*>(this)->DoSpecialWork(); } void DoBasicWork(){ std::cout << "Do Basic work..\n"; } }; class Derived1 : public Base<Derived1> { public: void DoSpecialWork(){ std::cout << "Do derived 1's special work..\n"; } }; class Derived2 : public Base<Derived2> { public: void DoSpecialWork(){ std::cout << "Do derived 2's special work..\n"; } }; int main() { Derived1 child1; Derived2 child2; child1.DoWork(); child2.DoWork(); return 0; } |
처음 예제와 같이 STL Container 에 저장하는 등의 동적 다형성이 필요하다면, 가상함수를 사용할수 밖에 없지만, 두번째 예제와 같은식으로 사용하는것으로 충분하다면 CRTP 를 이용한 방식도 고려해볼만 하겠다.
댓글 없음:
댓글 쓰기