为什么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?
我对 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?