2012-09-27 20 views
7

türlü varsayılan değerini almak için:Böyle bir şey yazabilirsiniz 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); 

    } 

ben C++ şablon sınıfı gibi bir sözlük yazmak niyetinde, ben varsayılan dönmek dicti istiyorum Verilen anahtarın bulunmaması durumunda jenerik TVal türünün değeri (sıfır). C# 'de, varsayılan (T) yapı kurtarmaya gelirken, C++' da aynı şeyi yapmanın uygun yolu olduğundan emin değilim.

gcc4.7 ile T obj = {} ve T* obj = {} denedim, iyi çalışıyor. Bu tür kod, taşınabilir çapraz derleyiciler ve platformlar olacaksa, dil belirtimi tarafından tanımlanan sözdizimi olursa emin değilim. Lütfen yardımcımla bana yardım et! Şimdiden teşekkürler!

PS:

~~~~~~~~~~

bile bunlardan çağrılabilir yok, şablon HERHANGİ BİR tipi varsayılan (sıfır dışında) değeri elde emin olmak için varsayılan ctor, ben (avakar cevabı esinlenerek) şu mekanizmayı istihdam:

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 
} 

Bu çirkin görünüyor, ama hepsi bir sıfırlanmasını nesne boş bellek sadece bir yığın sonra, herhangi bir sorun neden olmamalıdır. Yanlış mıyım?

+0

http://stackoverflow.com/questions/1962600/what-is-the-c-cli-eşdeğer-to-cs-defaultt – Khurshid

+0

Bu sorununuzu çözerse tamamen emin değilim, ama düşünüyorum [Boo st.Value Initialized] (http://www.boost.org/doc/libs/release/libs/utility/value_init.htm) bu sorunu çözmeye çalışır. –

cevap

19

C++ 'da C# default anahtar kelimesi gibi bir şey yoktur. Varsayılan yapıcı tarafından varsayılan türden başlatıcı başlatılamadığı için, varsayılan kurucu private'dur. C# 'de, varsayılan kurucu özelse, sınıf türü reference-type olduğundan, sınıf türünün değeri null olarak başlatılır. {} tarafından başlatılma, dil özelliklerine göre tanımlanmıştır. C++ 11. yorumunda bames53 tarafından belirttiği gibi C++ 03 yılında siz T* başlatmak istediğinizde C++ 11 önce

kullanmalıdır

T obj = T(); 

kullanmalıdır.

T* obj = 0; 

veya C++ 11

T* obj = NULL; 

.

T* obj = {}; 

veya

T* obj = nullptr; 
+0

Bu, işaretçi türleri için de çalışır mı? – Need4Steed

+4

'double * obj = double()' çalışmıyor. –

+1

@ Need4Steed, "works" ile işaretçinin varsayılan değerinin boş olduğu anlamına gelirse, işaretçi türleri için çalışır. "Eserler", "beklentilerimi karşıladığını" söylemenin kısa bir yoludur; Daha uzun ifade gibi, beklenen sonucun gerçekte ne olduğunu açığa vurmaz. Ama en azından kısa, – rici

3

"Bjarne Stroustrup tarafından C++ programlama dili, Üçüncü Baskı" dan literaly Taken:

QUOTE BEGIN

4.9.5 Başlatma [dcl.init]

Bir nesne için bir başlatıcı belirtilirse, bu başlatıcıyı belirler. bir nesnenin başlangıç ​​değeri. Başlatıcı belirtilmemişse, genel (§4.9.4), ad alanı (§8.2) veya yerel statik nesne (§7.1.2, §10.2.4) (topluca statik nesneler olarak adlandırılır), uygun türde 0'a başlatılır. .Örneğin:

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

Yerel (bazen otomatik nesneler olarak adlandırılır) değişkenleri ve ücretsiz deposunda oluşturulan nesneler varsayılan olarak başlatılmamış olan (bazen dinamik nesneler veya yığın nesneleri olarak adlandırılır). Örneğin: Dizi veya yapının statik olup olmadığına bağlı olarak dizilerin ve yapıların üyeleri varsayılan olarak başlatılmış veya değillerdir. Kullanıcı tanımlı türlerde varsayılan başlatma tanımlanmış olabilir (§10.4.2).

Daha karmaşık nesneler, başlatıcı olarak birden fazla değere gereksinim duyar. Bu, {ve} tarafından dizinin C-stili başlatılması için (§5.2.1) ve yapıların (§5.7) sınırlandırılan başlatıcı listeleri tarafından ele alınır.

Kurucularla kullanıcı tanımlı türler için, işlev stili argüman listeleri kullanılır (§2.5.2, §10.2.3). Bir beyannamede boş bir parantez() çiftinin her zaman "işlev" anlamına geldiğine dikkat edin (§7.1). Örneğin:

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

Ancak, T ('nin defaultut ctor'unu sildiysem veya özel olarak bildirdiysem, T()' çözümünün çalışmayı durdurduğunu öğrendim, ancak C# varsayılan (T) 'de zaten çalışıyor, bu yüzden tam anlamıyla çalışmıyor HER türü için! Ne bir setback1 – Need4Steed

+2

@ Need4Steed Evet, çünkü C# referans türleri ve değer tiplerine sahip. Tüm sınıf türleri referans türleridir ve null tarafından başlatılabilir, C++ böyle bir şey yoktur. – ForEveR

+2

Doğrudan C++ mucidinin en iyi cevabı. Neden bu cevabın bu kadar az oyu var? Utanç! Sağol Roy. –

3

sonsuza cevabı T Eğer burada çalışmaz:

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

SON QUOTE

Yani, herhangi bir tür varsayılan değeri bu tür bir statik nesne oluşturmak alabilirsiniz bir kopya kurucumuz var. C++ 03'te, hem genel hem de zarif olan bir değişkeni sıfırlamak için bir yol yoktur. Geriye kalan tek şey şu hiledir. Burada

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

, temp[0] sıfır başlatıldı ve ardından obj için bağlanır. Hiçbir kopya kurucuya ihtiyaç yoktur.

1

kendi varsayılan anahtar kelime oluşturma:

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

default_t const default = default_t(); 

hoşuna kullanın:

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

Veya hafif bir semantik varyasyon ile:

default_t const empty = default_t(); 

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

    return empty; 
} 
İlgili konular