2011-04-06 44 views
1

我想實現class Address,它在創建時將其字段addr初始化爲唯一值。每創建一個Address實例,該值必須遞增1。使用「奇怪的循環模板模式」的增量編號

讓我們來舉個例子。下面的代碼執行後:

Address x; 
Address y; 

x.addr應爲1,而y.addr應該爲2

爲了實現這個目標,我在想Curiously Recurring Template Pattern的。它可行嗎? 此外,是否有更簡單的方法來實現相同的行爲?

TIA, JIR

回答

7

你並不真的需要它在這裏,因爲你並不需要捕捉對象的破壞。你會注意到,維基百科頁面上的例子的逐筆共有多少個對象存在的類型,所以CRTP有兩個方便的功能:

  1. ,因爲它是一個基類,它的析構函數被調用(成員也會實現這一點)。
  2. 因爲它是在派生類類型上模板化的,所以從它繼承的每個類都有一個單獨的計數器,包括層次結構中的不同類,如果它們使用多重繼承來包含它們自己的CRTP庫,而不需要編寫大量代碼每班。

如果你只是想爲一個類的每個成員的唯一值,那麼線程安全的一邊,你可以做這樣的:

int get_id() { 
    static int counter = 0; 
    return ++counter; 
} 

class Address { 
    int addr; 
    public: 
    Address() : addr(get_id()) {} 
}; 

繼CRTP例如,您可以模板get_id和如果您有多個類進行跟蹤,並希望它們各自擁有自己的ID空間,請使用Address作爲參數。

對於這種用例,如果您確實使用了CRTP,則可以將數據成員addr置於模板基類中,如果您有很多類,則爲贏,因爲使用每個類的輸入較少它:

template <typename Derived> 
class unique_addr { 
    protected: 
    int addr; 
    unique_addr() : addr(get_id<Derived>()) {} 
}; 

class Address : public unique_addr<Address> { 
}; 

class OtherAddress : public unique_addr<OtherAddress> { 
}; 
+2

+1和'get_id'甚至可以是類的私有靜態功能,使之更實現的細節。請注意,如果您在多線程環境中運行,因爲所顯示的解決方案不是線程安全的。 – 2011-04-06 17:37:44

+0

清晰完整的說明!感謝你們! – Jir 2011-04-07 09:07:52

1

這似乎是你想要做的矯枉過正。如果您只需要一個唯一的值,則使用一個靜態整數並在您每次實例化一個對象時增加它。然後將每個實例(即非靜態)變量設置爲該值。

0

當然,您可以完全按照您引用的維基百科文章中所示的方式進行操作。 (除了聽起來好像你想減少dtor中的計數器一樣。)或者,如果你只需要它作爲Address類,那麼你可以做一次性的CRTP實現:

static int n_addresses = 0; 
class Address { 
    int addr; 
    Address() { addr = ++n_addresses; } 
}; 

或類似的東西。

0
public class Address 
{ 
    private static int addrCounter = 1; 

    public int addr { get; private set; } 

    public Address() 
    { 
     addr = addrCounter++; 
    } 
} 
0

您可以使用亦靜櫃檯內部類:

class Address 
{ 
    static int s_Count; // define this variable in appropriate cpp file 
    int addr; 
public: 
    Address() : addr(++ s_Count) {} 
};