본문 바로가기
개발/C, C++

C++ - CRTP로 인터페이스 만들기 (Interface with Curiously Recurring Template Pattern)

by 피로물든딸기 2024. 3. 6.
반응형

C, C++ 전체 링크

 

참고

- 형변환 연산자

- 가상 함수 테이블

 

C++인터페이스순수 가상 함수를 이용해서 만들 수 있다.

class Base
{
public:
	virtual void interface() = 0; // 순수 가상 함수
	void commonOperation() { cout << "Common Operation in Base class" << endl; }
};

 

파생 클래스DerivedBase순수 가상 함수로 정의된 interface() 메서드를 구현해야 한다.

class Derived1 : public Base
{
public:
	void interface() override { cout << "Implementation in Derived1" << endl; }
};

 

예제 코드는 다음과 같다.

#include <iostream>

using namespace std;

class Base 
{
public:
	virtual void interface() = 0; // 순수 가상 함수
	void commonOperation() { cout << "Common Operation in Base class" << endl; }
};

class Derived1 : public Base
{
public:
	void interface() override { cout << "Implementation in Derived1" << endl; }
};

class Derived2 : public Base 
{
public:
	void interface() override { cout << "Implementation in Derived2" << endl;}
};

int main() 
{
	Derived1* d1 = new Derived1();
	Derived2* d2 = new Derived2();

	d1->interface();
	d1->commonOperation(); 

	d2->interface(); 
	d2->commonOperation(); 

	return 0;
}


CRTP 패턴 적용

 

CRTP(Curiously Recurring Template Pattern)을 적용해서 C++의 인터페이스를 구현할 수 있다.

이 패턴은 기본 클래스 템플릿파생 클래스 템플릿 매개변수로 전달하여,

파생 클래스가 기본 클래스에 특정한 동작을 순수 가상 함수처럼 강제로 구현하도록 한다.

 

먼저 Base 클래스template으로 선언하고 inteface 메서드는 아래와 같이 수정한다.

interface 메서드 안에 있는 implementation파생 클래스에서 구현해야 할 메서드가 된다.

template <typename T>
class Base
{
public:
	void interface() { static_cast<T*>(this)->implementation(); }
	void commonOperation() { cout << "Common Operation in Base class" << endl; }
};

 

Derived에서는 implemantation을 구현하면 된다.

class Derived1 : public Base<Derived1>
{
public:
	void implementation() { cout << "Implementation in Derived1" << endl; }
};

 

전체 코드는 다음과 같다.

#include <iostream>

using namespace std;

template <typename T>
class Base 
{
public:
	void interface() { static_cast<T*>(this)->implementation(); }
	void commonOperation() { cout << "Common Operation in Base class" << endl; }
};

class Derived1 : public Base<Derived1>
{
public:
	void implementation() { cout << "Implementation in Derived1" << endl; }
};

class Derived2 : public Base<Derived2>
{
public:
	void implementation() { cout << "Implementation in Derived2" << endl;}
};

int main() 
{
	Derived1* d1 = new Derived1();
	Derived2* d2 = new Derived2();

	d1->interface();
	d1->commonOperation(); 

	d2->interface(); 
	d2->commonOperation(); 

	return 0;
}

 

CRTP를 적용할 때의 장점은 아래와 같다.

 

- CRTP가상 함수 호출이 발생하지 않기 때문에 런타임 오버헤드가 없다.

- 컴파일 타임에 다형성을 제공하고, 가상 함수 호출 대신 컴파일러 코드를 생성하므로 호출되는 함수가 미리 결정된다.

  (런타임에 다형성으로 인한 오버헤드 제거)

- 가상 함수 테이블(vtable)이 필요하지 않아서 프로그램 코드 크기가 감소한다.

반응형

댓글