45

“奇怪重复的模板模式”有哪些实际用途?通常显示的“计数类”示例对我来说并不是一个令人信服的示例。

4

5 回答 5

25

模拟动态绑定。在保留一些分层优势的同时避免虚函数调用的成本对于可以在我目前正在从事的项目中完成的子系统来说是一个巨大的胜利。

于 2008-09-29T16:03:32.353 回答
20

它对于mixin (我的意思是你继承的类以提供功能)也特别有用,它们本身需要知道它们正在操作什么类型(因此需要是模板)。

Effective C++中,Scott Meyers 提供了一个类模板 NewHandlerSupport<T> 作为示例。这包含一个静态方法来覆盖特定类的新处理程序(与 std::set_new_handler 对默认运算符 new 所做的相同),以及一个使用处理程序的运算符 new。为了提供每个类型的处理程序,父类需要知道它作用于什么类型,所以它需要是一个类模板。模板参数是子类。

如果没有 CRTP,您将无法真正做到这一点,因为您需要单独实例化 NewHandlerSupport 模板,并使用单独的静态数据成员来存储当前的 new_handler,每个使用它的类。

很明显,整个例子是非常非线程安全的,但它说明了这一点。

Meyers 认为 CRTP 可能被认为是“为我而做”。我想说这通常适用于任何 mixin,并且 CRTP 适用于您需要 mixin 模板而不仅仅是 mixin 类的情况。

于 2008-09-29T16:19:01.973 回答
4

如果您认为仅在方法扩展时才需要传递给超类的子类类型,那么 CRTP 就不会那么好奇了。所以所有类型都被定义了。您只需要将符号子类类型导入超类的模式,但它只是一个前向声明 - 因为所有正式模板参数类型都是按定义的 - 就超类而言。

我们以稍微修改的形式使用,将特征类型结构中的子类传递给超类,以使超类可以返回派生类型的对象。该应用程序是一个几何微积分库(点、向量、线、框),其中所有通用功能都在超类中实现,子类只定义了一个特定类型:CFltPoint 继承自 TGenPoint。CFltPoint 也存在于 TGenPoint 之前,因此子类化是一种自然的重构方式。

于 2008-09-29T18:17:59.643 回答
1

通常,它用于类似多态的模式,您不需要在运行时选择派生类,只需在编译时选择。这样可以节省运行时虚函数调用的开销。

于 2008-09-29T16:04:36.877 回答
1

对于 CRTP 的实际库使用,请查看 ATL 和 WTL (wtl.sf.net)。它在那里被广泛用于编译时多态性。

于 2008-10-02T09:52:38.693 回答