[모던 C++ 디자인 패턴] 1. 개요 #1 사전 개념
1. CRTP
“이상한 재귀 템플릿 패턴(Curiously Recurring Template Pattern)” 이라고 불린다! 디자인 패턴이라기보다는 C++에서 주로 사용하는 코드 패턴이라고 생각하자.
1
2
3
4
5
6
struct Foo : SomeBase<Foo>
{
...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
template <typename Derived>
struct SomeBase
{
void foo()
{
for(auto& item : *static_cast<Derivec*>(this))
{
...
}
}
}
위 코드와 같이 자기 자신을 베이스 클래스의 템플릿 인자로 상속받는다.
자기 자신을 상속하게 되면 베이스 클래스의 구현부에서 타입이 지정된 this
포인터를 사용할 수 있다.
일반적으로 상위 클래스는 서브 클래스의 객체를 순회할 수 없지만, CRTP를 적용하면 this
를 서브 클래스 타입으로 캐스팅할 수 있다.
2. 첨가(Mixin) 상속
클래스 인자를 정의할 때 자기 자신을 템플릿 인자로 할 수 있다.
1
2
3
4
5
6
template <typename T> struct Mixin : T
{
...
}
이러한 방식을 첨가 상속(mixin inheritance)이라고 한다.
첨가 상속을 이용하면 계층적으로 여러 타입을 형성할 수 있다.
eg) Foo<Bar<Baz>> x
와 같은 변수를 선언하면 새로운 타입 FooBarBaz
를 구현하지 않고 세 가지 타입의 속성을 가지게 할 수 있다!
3. 속성
일반적으로 C++에서 속성을 표현하는 방법은 아래와 같다.
1
2
3
4
5
6
7
8
9
class Person
{
int age;
public:
int get_age() const { return age; }
void set_age(int value) { age = value; }
};
C++ 자체의 기능으로 속성을 지원하지 않지만, 대부분의 컴파일러에서 비표준적인 방법으로 속성을 지원한다. 아래와 같이 코드를 작성하면 자동으로 get/set
메서드가 호출된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Person
{
int age_;
public:
int get_age() const { return age_; }
void set_age(int value) { age_ = value; }
__declspec(property(get=get_age, put=set_age)) int age;
}
int main()
{
Person p;
p.age = 20; // p.set_age(20)
}
Leave a comment