如果使用 CRTP,派生类方法是否会覆盖该方法的基类版本?

问题描述

几天前,我发现了一个有趣的 C++ 结构,名为 Curiously Recurring Template Pattern(通常缩写为 CRTP)。从那时起,我一直试图完全理解这个技巧是如何工作的。

假设我有以下代码片段

#include <iostream>

template<class T>
struct GraphicalObject
{
    void draw()
    {
        static_cast<T*>(this)->draw();
    }
};

struct Circle : GraphicalObject<Circle>
{
    void draw()
    {
        std::cout << "Drawing circle!" << std::endl;
    }
};

struct Square : GraphicalObject<Square>
{
    void draw()
    {
        std::cout << "Drawing square!" << std::endl;
    }
};

int main(int argc,char** argv) {
    
    Square s;
    Circle c;
    
    s.draw();
    c.draw();
    
    return 0;
}

CRTP 背后的所有“魔法”显然都在 static_cast<T*>(this)->draw() 行中。但是它是如何详细工作的呢?我的理解如下。假设我有 Circle c

如果编译器看到这个声明,它是一个信号,让他用参数 GraphicalObject 实例化 Circle 模板。我认为这会导致编译器创建 struct GraphicalObject<Circle>

struct GraphicalObject<Circle>
{
 void draw()
 {
  static_cast<Circle*>(this)->draw();
 }
};

因此创建了具有特殊版本的 draw 方法的结构。结构体 GraphicalObject<Circle> 构成了 Circle 结构体的基础结构体。

在第二步中,创建了 c 结构的实例 Circle,即调用了 Circle 的隐式构造函数。由于 Circle 是从 GraphicalObject<Circle> 继承的,因此首先调用该结构的隐式构造函数。在我看来,这会导致在 GraphicalObject<Circle> 对象内创建 c 的实例。这样对吗?然后我认为 draw 结构中声明的 Circle 方法覆盖了 draw 结构中声明的 GraphicalObject<Circle> 方法。但这对我来说没有意义。我宁愿期望来自 drawGraphicalObject<Circle> 方法的“专门”版本不会被覆盖。请您告诉我我对 CRTP 的工作原理的理解有什么问题?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)