2012-09-27 39 views
7

在C#中我可以寫這樣的事:如何獲得任何類型的默認值

class AnyThing<T> 
    { 
     static public T Default = default(T); 
    } 

    static void Main() 
    { 
     int i = AnyThing<int>.Default; 
     Console.WriteLine (i==0); 
     string s = AnyThing<string>.Default; 
     Console.WriteLine (s == null); 

    } 

我打算寫像在C++模板類一本字典,我想的字典返回默認如果找不到給定的鍵,則返回通用TVal類型的值(零出)。在C#中,默認的(T)構造來拯救,而在C++中,我不確定什麼是做同樣事情的適當方式。

我試過T obj = {}T* obj = {}與gcc4.7,它運作良好。我只是不太確定它是否是語言規範定義的語法,如果這種代碼是可移植的交叉編譯器和平臺。請幫助我與我的doudt!提前致謝!

PS:

~~~~~~~~~~

爲了確保模板得到任何類型的默認的(零出)值,即使那些不具有可贖回默認的構造函數,我採用以下機制(由avakar的回答啓發):

template<class T> 
struct AnyThing 
{ 
    static const T& Default ; 
private: 
    static const char temp[sizeof(T)]; 
}; 

template<class T> const char AnyThing<T>::temp[] = {}; 
template<class T> const T& AnyThing<T>::Default = *(T*)temp; 

struct st 
{ 
    double data; 
    st()=delete; 
}; 

int main() 
{ 
    cout << (int)AnyThing<char*>::Default<<endl; //0 
    cout << AnyThing<int>::Default<<endl;  //0 
    cout <<AnyThing<st>::Default.data<<endl;  //0 
} 

它看起來醜陋,但應該不會造成任何麻煩,畢竟是一個歸零的對象僅僅是一個空白內存塊。我錯了嗎?

+0

http://stackoverflow.com/questions/1962600/what-is-c-cli-equivalent-to-cs-defaultt – Khurshid

+0

我不完全確定這是否解決了你的問題,但我認爲[Boo st.Value Initialized](http://www.boost.org/doc/libs/release/libs/utility/value_init.htm)試圖解決這個問題。 –

回答

19

在C++中,沒有類似於C#中的default關鍵字。由於缺省構造函數的默認構造函數是private,因此類類型值的默認構造函數的初始化將失敗。在C#中,如果默認構造函數是私有的,那麼class-type的值將被初始化爲null,因爲class-type是reference-type

{}的初始化由語言規範定義。這是C++ 11。在C++ 03,你應該使用

T obj = T(); 

正如指出在評論bames53,當你想初始化T*你應該之前C++ 11使用

T* obj = 0; 

T* obj = NULL; 

在C++ 11。

T* obj = {}; 

T* obj = nullptr; 
+0

這也適用於指針類型嗎? – Need4Steed

+4

'double * obj = double()'不起作用。 –

+1

@ Need4Steed,它適用於指針類型,如果用「works」表示指針的默認值爲null。 「作品」是「滿足我的期望」的簡短方式;像更長的短語一樣,它沒有揭示預期的結果實際上是什麼。但至少它很短, – rici

3

選自 「C++編程語言,第三版由Bjarne Stroustrup的」 literaly摘自:

BEGIN QUOTE

4.9.5初始化[dcl.init]

如果爲對象指定了初始化程序,則該初始化程序將確定對象的初始值。如果未指定初始化程序,則將全局(§4.9.4),名稱空間(§8.2)或本地靜態對象(§7.1.2,§10.2.4)(統稱爲靜態對象)初始化爲適當類型的0 。例如:

int a; // means int a=0; 
double d; // meands d=0; 

局部變量(有時稱爲自動對象)並在自由存儲區創建的對象(有時稱爲動態對象或堆對象)不默認情況下初始化。例如:

void f() 
{ 
    int x; // x does not have a well-defined value 
    // . . . 
} 

數組和結構的成員是默認初始化或不是取決於數組或結構是靜態的。用戶定義的類型可能有默認的初始化定義(§10.4.2)。

更復雜的對象需要多個值作爲初始值設定項。這是由{和}爲數組(§5.2.1)和結構體(§5.7)的C風格初始化定界的初始值設定項列表處理的。

對於具有構造函數的用戶定義類型,使用函數式參數列表(§2.5.2,§10.2.3)。請注意,聲明中的一對空括號()總是意味着「函數」(第7.1節)。例如:

int a[] = {1,2}; // array initializer 
Point z(1,2);  // function-style initializer (initialization by constructor) 
int f();   // function declaration 

最終報價

所以,你可以得到任何類型的默認值形成類型的靜態對象:

static T defaultT; // `defaultT' has de default value of type T 
+0

但是我發現如果我刪除了T的默認值,或者將它聲明爲私有,但是在C#中默認(T)''工作,'T()'解決方案停止工作,所以它不能真正工作爲任何類型!什麼是setback1 – Need4Steed

+2

@ Need4Steed是的,因爲C#有引用類型和值類型。所有的類型都是引用類型,可以用null初始化,C++沒有這種東西。 – ForEveR

+2

最佳答案,直接來自C++的發明者。爲什麼這個答案有這麼幾票?恥辱!謝謝,羅伊。 –

3

永遠的回答不會,如果T沒有按工作沒有複製構造函數。在C++ 03中,沒有辦法對通用和優雅的變量進行零初始化。剩下的就是以下技巧。

T temp[1] = {}; 
T & obj = temp[0]; 

這裏,temp[0]是零初始化,然後結合到obj。不需要複製構造函數。

1

創建自己的默認關鍵字:

class default_t 
{ 
public: 
    template<typename T> 
    operator T() const { return T(); } 
}; 

default_t const default = default_t(); 

這樣使用它:

int myInt = default; 
vector<string> myVector = default; 
shared_ptr<string> myPtr = default; 

還是有輕微的語義變化:

default_t const empty = default_t(); 

vector<Persons> fetchPersons() 
{ 
    if (Database::isConnected()) 
    { 
    return Database::fetchPersons(); 
    } 

    return empty; 
} 
相關問題