일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 티스토리챌린지
- 상속
- 다형성
- 메타테이블
- 암시적 변환
- operator new
- 반복자
- 예외
- c++
- 영화
- lua
- Effective c++
- 게임
- Vector
- 오블완
- 루아
- exception
- implicit conversion
- resource management class
- virtual function
- more effective c++
- 언리얼
- 참조자
- 스마트 포인터
- effective stl
- 영화 리뷰
- UE4
- Smart Pointer
- reference
- 비교 함수 객체
Archives
- Today
- Total
스토리텔링 개발자
[Effective C++] 41. 템플릿 프로그래밍 본문
728x90
항목 41. 템플릿 프로그래밍의 천릿길도 암시적 인터페이스와 컴파일 타임 다형성부터
객체 지향 프로그래밍의 축
- 명시적 인터페이스(explicit interface)
- 명시적으로 적시된 인터페이스를 통해 객체를 활용할 수 있다.
- 런타임 다형성(runtime polymorphism)
- 런타임에 객체의 타입을 유동적으로 체크한다.
class Widget
{
public:
Widget();
virtual ~Widget();
virtual std::size_t size() const;
virtual void normalize();
void swap(Widget& other);
...
};
void doProcessing(Widget& w)
{
if(w.size() > 10 && w != someNastyWidget)
{
// 헤더 등에서 Widget 인터페이스를 지원해야 한다.(명시적 인터페이스)
Widget temp(w);
// virtual 함수를 호출한다.(런타임 다형성)
temp.normalize();
temp.swap(w);
}
}
템플릿과 일반화 프로그래밍의 축
- 암시적 인터페이스(implicit interface)
- 인터페이스가 명확히 적시되어 있지 않아도 특정 인터페이스가 있음을 가정할 수 있다.
- 컴파일 타임 다형성(compile-tiem polymorphism)
- 컴파일 타임에 타입 형식을 결정한다.
template<typename T>
void doProcessing(T& w)
{
// w가 수반되는 함수 호출이 일어날 때,
// 해당 호출을 성공시키기 위해 템플릿의 인스턴스화(w의 인스턴스화)가 일어난다.
// 이 인스턴스화는 컴파일 도중에 발생한다.
// 그리고 어떤 템플릿 매개변수냐에 따라 호출 함수가 달라진다.(컴파일 타임 다형성)
if(w.size() > 10 && w != someNastyWidget)
{
// w의 인터페이스는 w에 대해 실행되는 연산이 결정한다.
// 이 템플릿이 컴파일되려면 몇 개의 표현식이 유효해야 한다.(암시적 인터페이스)
// 이 경우 복사 생성자, normalize, swap를 지원하는 인터페이스여야 한다.
T temp(w);
temp.normalize();
temp.swap(w);
}
}
런타임 다형성, 컴파일 타임 다형성
- 런타임 다형성
- 가상 함수 호출의 동적 바인딩과 흡사하다.
- 컴파일 타임 다형성
- 오버로드된 함수 중 지금 호출할 것을 골라내는 과정과 흡사하다.
명시적 인터페이스, 암시적 인터페이스
- 명시적 인터페이스
- 함수 시그니처 기반으로 이루어진다.
- 생성자, 소멸자, 함수, 매개변수 타입, 반환 타입, 각 함수의 상수성 여부.
- typedef 타입이 있을 경우 이것 역시 포함될 수 있다.
- 데이터 멤버의 경우 포함되지 않는다.(public으로 공개되어 있다고 하더라도)
- 암시적 인터페이스
- 유효 표현식(expression) 기반으로 이루어진다.
-
template<typename T> void doProcessing(T& w) { // 암시적 인터페이스 제약 // 1. 정수 계열 값을 반환하는 이름이 size인 함수가 있어야 한다. // 2. T 타입 객체 둘을 비교하는 operator!= 함수를 지원해야 한다. // (someNastyWidget이 T 객체라는 가정 하에) if(w.size() > 10 && w != someNastyWidget) { T temp(w); temp.normalize(); temp.swap(w); } }
- 실제로는 T는 위 주석의 두 가지 제약 중 어떤 것도 만족시킬 필요가 없다.
- size 함수의 경우
- T가 size 멤버 함수를 지원해야 한다. 하지만 수치 타입을 반환할 필요는 없다.
- 즉, size 멤버 함수가 반환하는 어떤 x 타입 객체와 int가 함께 호출될 수 있는 operator>가 성립된다면, 어떤 값을 반환해도 된다.
- 심지어 operator> 함수가 x 타입을 받아들일 필요도 없다. X 타입이 operator> 함수가 받아들이는 매개변수로 암시적 변환만 가능해도 된다.
- operator!= 함수의 경우
- operator!= 함수가 X 타입, Y 타입 객체를 받아들인다고 하면..
- T타입이 X로 변환될 수 있고, someNastyWidget 타입이 Y로 변환될 수만 있다면 성공 가능하다.
- size 함수의 경우
- 세세한 제약을 일일이 따질 필요 없이, 전체적인 제약만 맞으면 OK.
- 결과적으로 doProcessing 템플릿이 타입 매개변수 T에 대해 요구하는 암시적 인터페이스란?
- 해당 표현식의 경우, if 문에 만족하는 boolean 표현식이기만 하면 된다.
- 복사 생성자, normalize, swap 함수에 대한 호출이 T 타입 객체에 대해 '유효'하기만 하면 된다.
728x90
'개발 > Effective C++' 카테고리의 다른 글
[Effective C++] 43. 템플릿 부모 클래스의 인터페이스에 접근하기 (0) | 2024.07.15 |
---|---|
[Effective C++] 42. typename의 두 가지 용법 (0) | 2024.07.12 |
[Effective C++] 40. 다중 상속 (0) | 2024.07.10 |
[Effective C++] 39. private 상속 (0) | 2024.07.09 |
[Effective C++] 38. 객체 합성 (0) | 2024.07.08 |
Comments