2016-10-03 13 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- (2)(http://stackoverflow.com/questions/652155/invalid-use-of-incomplete-type)を参照してください)。 'T'は完全に完全な型ではないので、コンパイラはこの状況で無限に再帰する必要はありません。少なくともそれは私の理解です。 – Cornstalks

+0

@Eichhörnchen私は基底から継承したDerivedによってテンプレート化されたBaseから継承したDerivedによってテンプレート化されたBaseから派生しているので... –

+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>は単なるクラスです。とてもシンプルなクラスです。それより簡単なことはできません。方法はありません。メンバーはいません。私的でも、保護されていたり、公的でもない。それは小さなクラスですが、他のクラスと同じ権利と特権を持っています。あなたはそれへのポインタを宣言することができます。またはそれへの参照。それは単なるクラスです。

ここでも、重要な概念は、テンプレートのインスタンスが単なるクラスであることです。パラメータであるクラスからテンプレートへの「継承」はありません。この場合、テンプレートインスタンスは完全に空ですが、他のクラスが実行できるものはすべて実行できます。パブリック、プライベート、および保護されたメンバーを持つことができます。他のクラスから派生することもできます(テンプレートインスタンスは単なるクラスなので)。テンプレートインスタンスは単なるクラスであるため、他のクラスもテンプレートインスタンスから派生することができます。

ここに無限のネスティングはありません。別のクラスから継承しているクラスが1つだけあります。 2番目のクラスはテンプレートインスタンスになりますが、テンプレートインスタンスは単なるクラスであると言われましたか?

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. 
} 
関連する問題