2016-10-03 6 views
6

CRTP 컴파일 방법에 대해 혼란스러워합니다. 우리가 이런 식으로하면 :왜 CRTP가 무한 중첩을 일으키지 않습니까?

template<class T> 
class Base 
{ 

}; 
class Derived : public Base<Derived> 
{ 

}; 

컴파일하는 동안 왜 이와 비슷한 일이 발생하지 않습니까?

Derived d;

d 템플릿과 유산

d[Base<Derived[Base<Derived[Base<Derived[Base<Derived[...]>]>]>]>]

이유 무한 반복으로 확장되고있는 Derived 인스턴스 선언되면

(X[Y]는 X가 Y 상속 나타낸다) 이런 일은 일어나지 않습니까? CRTP에 대한 모든 자습서에서는 사용자가 수행 할 수있는 작업에 대해서만 설명합니다 (최소한 희미하게).

+0

'Base'문맥에서 'T'는 완전한 형식이 아닙니다. 이 때문에'Base'에서'T'에 정의 된'typedef'와 같은 것에 접근 할 수 없습니다 ([1] (http://stackoverflow.com/questions/6006614/c-static-polymorphism-crtp- and-using-typedef-from-derived-classes) 및 [2] (http://stackoverflow.com/questions/652155/invalid-use-of-incomplete-type)를 참조하십시오. 'T'는 완전히 완전한 타입이 아니기 때문에 컴파일러는이 상황에서 무한히 재귀 할 필요가 없습니다. 적어도 그것은 나의 이해입니다. – Cornstalks

+0

@ Eichhörnchen 왜냐하면 Base에서 파생 되었기 때문에, Base로부터 상속받은 Base에서 상속받은 Derived에 의해 템플릿이 만들어 졌기 때문입니다. –

+0

@Cornstalks는 오른쪽에 대해 소리가납니다. –

답변

7

기본적인 개념은 이해하기 템플릿의 인스턴스 그냥 클래스 것입니다. 근본적으로 다른 클래스와 다르지 않습니다.

template<typename T> class Base; 

그런 다음 템플릿 인스턴스 : 당신은 전형적인 템플릿 정의가있는 경우

Base<int> 

그 이름의 단지 클래스입니다. int과는 아무런 관련이 없으며 int과는 전혀 관계가 없습니다. 그것은 어떤 식 으로든 어떤 방식 으로든 그것을 상속하지 않습니다.

다음 단계 :

class Derived; 

template<typename T> class Base {}; 

Base<Derived> foo; 

다시 Base<Derived> 그냥 클래스입니다. Derived과 본질적인 관계가 없습니다. 그것은 파생되지 않으며, 파생되지 않습니다. 이 Base<Derived>라는 클래스에서 상속 Derived라는 클래스를 선언

template<class T> 
class Base 
{ 

}; 

class Derived : public Base<Derived> 
{ 

}; 

:

그래서, 이제 우리는 마지막 단계를 취할. Base<Derived>은 수업 일뿐입니다. 아주 간단한 수업입니다. 그보다 더 간단해질 수는 없습니다. 그것은 어떤 방법도 가지고 있지 않습니다. 회원이 없습니다. 개인, 보호 또는 공개하지 않습니다. 그것은 작은 클래스이지만 다른 클래스와 동일한 권리와 특권을가집니다. 포인터를 선언 할 수 있습니다. 또는 그것에 대한 참조. 그것은 단지 수업입니다.

다시 한번 핵심 개념은 템플릿의 인스턴스가 단지 클래스라는 것입니다. 템플릿의 매개 변수 인 클래스에서 어떤 식 으로든 "상속"하지 않습니다. 이 경우 템플릿 인스턴스는 완전히 비어 있지만 다른 클래스에서 수행 할 수있는 모든 작업을 수행 할 수 있습니다. 공개, 비공개 및 보호 된 구성원이있을 수 있습니다. 다른 템플릿 클래스 (템플릿 인스턴스는 클래스 일 뿐이므로)가 될 수있는 다른 클래스에서 파생 될 수 있습니다. 또는 템플릿 인스턴스가 클래스 일 뿐이므로 다른 클래스가 템플릿 인스턴스에서 파생 될 수 있습니다.

여기에 무한 중첩이 없습니다. 다른 클래스에서 상속받은 하나의 클래스 만 있으면됩니다. 두 번째 클래스는 템플릿 인스턴스가 되겠지만 템플릿 인스턴스는 클래스 일뿐입니다.

3

간단한 설명 : 다음은 완전히 유효하기 때문에 :

template<class T> 
class Base 
{ 
}; 

class Derived /* at this point, Derived is declared (not defined) */; 

int main() 
{ 
    Base<Derived> base; // the definition of Derived (or lack thereof) is irrelevant. 
}