2013-01-03 121 views
1

有什麼東西我不明白我希望你注意下放,請檢查這些代碼片段:從基類的靜態鑄造衍生

template< typename DerivedClass > 
class construction_management 
{ 
    city* this_city; 
public: 
    construction_management() 
    { 
     this_city = static_cast< city* >(this); 
    } 
    ~construction_management(); 
}; 

我刪除故意所有沒有必要的代碼,請看看這使this指針的靜態強制轉換爲類型「城市」,這是因爲下面定義的構造函數:

class city : public construction_management<city> 
{ 

public: 

public: 
    city(const string& name, const string& owner); 
}; 

類是故意空的,因爲我覺得沒有什麼,它可以包含與此有關。希望我在100%無法理解這裏發生了什麼,g ++ 4.7.2在編譯階段不打印警告或錯誤,並且每當我使用'this_city'指針時,我都可以訪問城市的所有公共成員,該對象本身看起來是一致的,因爲所有變量都被正確初始化並且包含始終有效的數據。

我想知道的是,爲什麼如果我將construction_management定義爲一個普通的非模板類,此代碼不起作用?由於從const轉換爲非const指向城市的轉換,轉換失敗,爲什麼?

這是錯誤的打印:

game.hpp: In constructor 'city_manager::construction_management::construction_management()': 
game.hpp:164:41: error: invalid static_cast from type 'city_manager::construction_management* const' to type 'city_manager::city*' 

爲什麼工作,如果construction_management是模板?這是一種CRTP嗎?

謝謝大家。

+1

我會說這*是* CRTP。您正在使用它自己的基礎創建派生類的模板實例。 AFAIK這是CRTP。 –

回答

4

它是CRTP,因爲懶惰的模板實例化而工作。

線:

this_city = static_cast< city* >(this); 

要求this到可以轉換成一個city*。如果city是從construction_management派生的,那確實有效。然而,基類必須有前派生類完整的聲明,所以只有一個編寫方式:

//template code may or may not be present 
class construction_management {...}; 
//maybe more code here 
class city: public construction_management {...}; 

如果基類是不是一個模板,它是實例化時,編譯器第一次看到的代碼。然後編譯器運行到構造函數中,它不知道city是從construction_management(或者甚至是什麼city,如果它沒有被聲明爲不完整類型)派生出來的。但是,如果基類是一個模板,那麼當聲明繼承時(不管怎麼樣,我都不是這方面的專家),它就是實例化的。此時,編譯器知道cityconstruction_management<city>派生,並且一切正常。

出於同樣的原因,如果將構造函數定義移動到稍後編譯的文件(很可能從.h到.cpp),它也可以不使用模板。

+0

嗡嗡聲,工作正常,如果我把代碼構造函數在cpp中。我現在唯一的困惑是關於如何從設計和優雅的角度來看這樣的代碼。我需要訪問城市中的一些元素,這些元素不允許作爲施工管理中的成員出現,例如,在城市中封裝了'player_info'結構,但是施工管理也需要包含在該結構中的一些信息城市繼承的另一個類),這就是爲什麼我使用基類中的this_city指針。 – fjanisze

+0

將代碼放在.cpp文件中是非常標準的,甚至當_it無法正常工作時更是如此。唯一不應該這樣做的地方是編寫模板時(這就是爲什麼構造函數代碼位於代碼的原始模板版本的頭文件中)。 –

+0

我的想法是關於指針'this_city'的用法,那個演員,我應該看看你的意見中的不同解決方案,還是沒有我想象的那麼糟糕? (我不知道爲什麼,但不知何故,我儘量避免投射操作)。 – fjanisze