为什么CRTP不会造成无限嵌套?

Why does CRTP not cause infinite nesting?

我对 CRTP 的编译方式感到困惑。如果我们有这样的东西:

template<class T>
class Base
{

};
class Derived : public Base<Derived>
{

};

为什么在编译过程中没有发生类似的事情?

(X[Y]表示X继承自Y)

在声明 Derived 实例时 Derived d;

d 正在扩展为模板和继承的无限循环

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

为什么这没有发生?所有关于 CRTP 的教程都只解释了你可以用它做什么,而不是在幕后发生了什么(至少是模糊的)。

简单解释:因为以下是完全有效的:

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.
}

要理解的基本概念是模板的实例就是 class。它与任何其他 class.

从根本上没有什么不同

当您有一个典型的模板定义时:

template<typename T> class Base;

然后模板实例:

Base<int>

只是那个名字的 class。它与 int 无关,与 int 完全没有任何关系。它不以某种方式或以任何方式从它继承。

下一步:

class Derived;

template<typename T> class Base {};

Base<Derived> foo;

同样,Base<Derived> 只是一个 class。与Derived没有内在联系。它不是从它派生的,也不是从它继承的,什么都没有。

所以,现在我们进行最后一步:

template<class T>
class Base
{

};

class Derived : public Base<Derived>
{

};

这声明了一个名为 Derived 的 class,它继承自一个名为 Base<Derived> 的 class。而 Base<Derived> 只是一个 class。很简单class。没有比这更简单的了。它没有任何方法。它没有任何成员。也不是私有的、受保护的或 public。它很小 class,但它拥有与任何其他 class 相同的权利和特权。您可以声明一个指向它的指针。或者对它的引用。这只是一个 class.

同样,关键概念是模板的实例只是一个 class。它不会以任何方式 "inherit" 从作为模板参数的 class 。在这种情况下,模板实例是完全空的,但它可以做任何其他 class 可以做的事情。它可以有 public、private 和 protected 成员。它可以派生自其他一些 class,这可能是另一个模板实例(因为模板实例只是一个 class)。或者,其他一些 class 可以从模板实例派生,因为模板实例只是一个 class.

这里没有无限嵌套。您只有一个 class 继承自另一个 class。第二个 class 恰好是一个模板实例,但我有没有提到模板实例只是一个 class?