簡體   English   中英

如果使用 CRTP,派生的 class 方法是否會覆蓋該方法的基本 class 版本?

[英]Does the derived class method override the base class version of the method in case the CRTP is used?

幾天前,我發現了一個有趣的 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

萬一編譯器看到這個聲明,這是他用參數Circle實例化GraphicalObject模板的信號。 我認為這會導致編譯器創建 struct GraphicalObject<Circle>

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

因此創建了具有特殊版本的draw方法的 struct。 struct GraphicalObject<Circle> forms 是Circle結構的基礎結構。

在第二步中,創建Circle結構的實例c ,即調用Circle的隱式構造函數。 由於Circle是從GraphicalObject<Circle>繼承的,因此首先調用該結構的隱式構造函數。 在我看來,這會導致在c object 中創建GraphicalObject<Circle>的實例。 這樣對嗎? 然后我認為Circle結構中聲明的draw方法覆蓋了GraphicalObject<Circle>結構中聲明的draw方法。 但這對我來說沒有意義。 我寧願期望來自GraphicalObject<Circle>draw方法的“專用”版本不應被覆蓋。 請你能告訴我我對 CRTP 工作原理的理解有什么問題嗎?

你沒有在main中做任何多態的事情來展示 CRTP 的特性。 試試這個,看看會發生什么:

template <typename T>
void drawObject(GraphicalObject<T>& obj) {
    obj.draw();
}

int main() {
    Square s;
    Circle c;
    
    s.draw();
    c.draw();

    drawObject(s);  // what happens here?

    GraphicalObject<Circle>& c_ref = c;
    drawObject(c_ref);  // what happens here?
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM