Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/hadoop/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么我要在静态多态性的简单模板上使用CRTP?_C++_Crtp - Fatal编程技术网

C++ 为什么我要在静态多态性的简单模板上使用CRTP?

C++ 为什么我要在静态多态性的简单模板上使用CRTP?,c++,crtp,C++,Crtp,我已经读了很多关于模板编程的帖子,但我仍然不明白为什么我不想仅仅使用模板编程 下面是一个从维基百科略加修改的示例: template <class T> struct Base { void interface() { static_cast<T*>(this)->implementation(); } }; struct Derived : Base<Derived> { void implement

我已经读了很多关于模板编程的帖子,但我仍然不明白为什么我不想仅仅使用模板编程

下面是一个从维基百科略加修改的示例:

template <class T> 
struct Base
{
    void interface()
    {
        static_cast<T*>(this)->implementation();
    }
};

struct Derived : Base<Derived>
{
    void implementation();
};
模板
结构基
{
void接口()
{
静态_cast(this)->implementation();
}
};
派生结构:基
{
无效实现();
};
但是,我可以用更直接的方式使用just template执行完全相同的操作:

template <class T> 
struct OuterClass
{
    void interface()
    {
        nested->implementation();
    }
private:
    T* nested;
};

struct NestedClass
{
    void implementation();
};

OuterClass<NestedClass> x;
x.interface();
模板
结构外部类
{
void接口()
{
嵌套->实现();
}
私人:
T*嵌套;
};
结构嵌套类
{
无效实现();
};
外类群x;
x、 接口();
CRTP与我的实现相比有什么优势


编辑:行
T*嵌套
as成员变量也可以是
T嵌套的使得嵌套的
由外部类的构造函数创建。

提供的解决方案几乎是基于多态性的虚拟函数的自制(假设样本不完整,并且在其他地方有一些代码实际设置了
T*

运行时多态性(aka类型擦除)的主要缺点是性能。由于需要取消引用指针,编译器通常无法在编译时知道调用了哪个函数,因此无法内联函数并决定函数的副作用。最重要的是,通过指针调用通常需要一个额外的指针解引用步骤,这也会减慢速度

我也能做到

不,您有一个额外的数据成员“T*nested”,它是在运行时设置的。因此,编译器不完全了解它将看到的确切对象,并且可能优化得不太理想。此外,如果使用“this”,则会有一个通过指针的间接寻址,因为对任何数据成员的访问在编译时都是已知的,即使调用的作者必须编写
static\u cast(this)->某些内容,但完整的操作在编译时是完全已知的

您所做的更像是一个虚拟函数调用,而不是编译时多态性

此外,您还必须将嵌套指针设置在某个位置,这意味着通过构造函数的内容,这在代码和速度方面也是开销


最后,我看到,你们需要分两步创建你们的对象。首先是“嵌套”类,然后将其指针传递给外部类。这还可能导致性能下降,并可能产生副作用,如非连续内存、缓存线未命中等。

我能想到的最简单的答案是,在后一种情况下,使用此接口的开发人员需要知道类型是如何组合的——他们必须明确地说
OuterClass
。在CRTP案例中,特别是对于私有继承,这是一个他们不必知道的细节。旁注:在第二个示例中,
OuterClass::nested
未初始化。提供“T*nested”的是什么?@Klaus它总是默认提供的constructor@cdhowie关于你说的第一点,我可以用typedef来解决这个问题。等等。。。在第二种情况下(除非
T::implementation()
是虚拟的),编译器在编译时确实知道完整的操作。我在这里看到的唯一次优的事情是对任何
*嵌套的
数据成员的附加间接寻址级别。方法调用仍然以与CRTP方法相同的方式进行调度。@cdhowie“在编译时知道完整的操作”否!如果对方法的调用不需要数据成员访问,则可以将其设置为静态。因此,它总是附加间接的!数据可能有额外的间接寻址,但这使编译器在运行时之前甚至无法解析最终的函数调用,这是错误的。编译器确切地知道将调用哪个函数(同样,假设该函数是非虚拟的),但直到运行时它才知道这个
将是什么。它可能仍然会进行大量优化,包括函数调用的内联。@cdhowie:它知道如何访问代码,但不知道如何访问数据!调用从给定对象访问数据的方法(在编译时未知)会导致优化效果较差。再次说明:如果在方法调用中不访问对象的数据,则将方法设置为静态。在这种情况下,您根本不需要指针,但这与运行时或编译时多态性无关。@Klaus我不同意。我不需要使用指针T*,只需要使用一个成员变量“T嵌套”,它是从OuterClass的默认构造函数创建的。在这种情况下,一切都是在编译时知道的。