2010-07-20 11 views
5

yerine başlatılmamış bir yer tutucu değişkeni oluşturma Şu anda Java'dan C++'ye geçiyorum ve Java'da yaygın olarak kullanılan bir kavram doğrudan C++ ile eşleşmediğinde bazı zorluklar yaşıyorum. Örneğin, Java gibi bir şey yapacağını: C, TabiiC++: Varsayılan nesne

Fruit GetFruit(String fruitName) { 
    Fruit fruit; 
    if(fruitName == "apple") fruit = new Fruit("apple"); 
    else if(fruitName == "banana") fruit = new Fruit("banana"); 
    else fruit = new Fruit("kumquat"); //'cause who really wants to eat a kumquat? 

    return fruit; 
} 

++ Fruit fruit; deyimi aslında bir meyve oluşturur. Bu, varsayılan bir kurucunun olması gerektiği anlamına mı geliyor? Bu güvenli değil! Varsayılan meyvem kaçarsa ne olur?

+4

Varsayılan meyve kaçar ve şehri terörize ederse ne olur? Hayır, cidden, 'kaçtı' ile ne demek istiyorsun? –

+8

_ Killer Kumquats'ın tacizi!_ –

+2

Daha ciddi bir notta: [önceki sorunuza] yanıt olarak çözümlerle ilgili sorun nedir? (Http://stackoverflow.com/questions/3285970/c-and-returning-a-null-what-worked- in-java-iş-içinde-c görünmez)? Sanırım bu soruya verilen cevapların bu soruya nasıl cevap vermediğini göremiyorum. –

cevap

9

C++ size çok daha verir meyve yaratmaya geldiğinde baş ağrısı. İhtiyaçlarınıza bağlı olarak, aşağıdaki seçeneklerden birini seçebilirsiniz:

1) bir kopyasını (bir kopya kurucu gereken bir yığın bir meyve oluşturmak ve dönüş) sonra ve adı, söz konusu durumda bazı varsayılan meyve sağlaması gerekir maç:

Fruit GetFruit(const std::string &name) 
{ 
    if (name == "banana") return Fruit("banana"); 
    if (name == "apple") return Fruit("apple"); 
    return Fruit("default"); 
} 

2) yere bu meyveyi silmek ve onu aşağıdaki ölçütlere göre yalnızca bir kez olmak silinir bakmak hatırlamak da bir yığın bir meyve oluşturmak ve boş-gösterici döner olabileceğini, özen ve sahibi (ve silinen meyveye bir işaretçinin sahip olduğuna dikkat edin):

3) ve son olarak, olası bir çok işaretçi sorununu önlemek için bir akıllı işaretçiyi kullanın (ancak boş göstericilere dikkat edin).Bu seçenek Java programlama deneyimi en yakın olan: bir bir nesne arasındaki fark (yani hafızada bir varlıktır) ve onun adresi vardır: C

typedef boost::shared_ptr<Fruit> FruitRef; 

FruitRef GetFruit(const std::string &name) 
{ 
    if (name == "banana") return new Fruit("banana"); 
    if (name == "apple") return new Fruit("apple"); 
    return FruitRef(); 
} 
+0

+1, shared_ptr yanıtıdır, derleyiciniz muhtemelen share_ptrs tr1 olarak – Patrick

+5

tr olarak desteklenmeden bir uygulamaya sahiptir. 4. Dinamik ayırmayı önlemek istiyorsanız 'boost :: isteğe bağlı ' seçeneğini kullanın. –

+0

@Mike Seymour. Hiç destek duymadım :: isteğe bağlı. Yorumunuz için teşekkürler =) – SadSido

1

Örneğinizi C++ ile eşlemek için işaretçiyi kullanmalısınız. C++ 'da, yerleşik bir nesne geçerli bir nesne olarak kabul edilir (bu nedenle referans olarak boş olamaz).

Kullanma Meyve * fruit = 0; ...

İhtiyacınız için varsayılan bir nesneye sahip olabilirsiniz veya herhangi bir test geçilmezse varsayılan varsayılan 0 olabilir.

+1

İşaretçi yaklaşımı oldukça standart mı? Yoksa bir nedenden dolayı garip mi? – JnBrymn

+1

@John: İşaretçi yaklaşımı standarttır. Bir Java programlayıcısına garip gelebilir, ama yine de Java'da bir C++ programcısına garip görünen şeyler var. C++ kullanacaksanız, bir çeşit işaretçiyi kullanmanız gerekir. –

+0

bu kötü değil, ancak işaretçiyi daha sonra silmeye dikkat etmelisiniz. Ya da bir akıllı işaretçi kullanabilirsiniz (bu, referansları sayan ve artık kimse kullanmadığında kendini silen bir işaretçidir). – Scharron

0

Java'daki fruit değişkeniniz yaklaşık olarak bir C++ işaretçisiyle eşleşiyor. Haklısınız, nesneyi yığında oluşturmak istemezsiniz, sadece yarattığınız yeni nesneye bir işaretçi istersiniz. Bu yüzden'u Fruit* olarak değiştirirseniz, bu işlev çalışır (işlev türü de değiştirirseniz). Sadece bu fonksiyondan geri döndüğünüz işaretçi delete olmalıdır, new s temizlemek için hiçbir çöp toplama yok.

6

Java'daki nesneler, işaretçilerle temsil edilir. Bu yaygın olduğundan, işaretçiler için özel bir işaret yoktur. C++ 'da, nesneler kendileri veya işaretçiler tarafından temsil edilebildiğinden, bunlar gerçekleştiğinde işaretçilerin belirtilmesi gerekir. kodunuzun

C++ sürümü:

Fruit * GetFruit(std::string fruitName) { 
    Fruit * fruit = 0; 
    if (fruitname == "apple") fruit = new Fruit("apple"); 
    else if (fruitname == "banana") fruit = new Fruit("banana"); 
    else fruit = new Fruit("kumquat"); 

    return fruit; 
} 

Bu Fruit bir işaretçi döndürür. fruit->color() gibi üyelere fruit.color()'dan değil. Bununla birlikte işaretçiyi delete olmalıdır.

+1

Java nesnesinde. Paylaşılan işaretçi eşdeğeridir. İşaretçiyi döndürmek, kod kokusunun veya C kodunun (benim için aynı şey) bir işaretidir. :-) –

2

en basit şekilde olacaktır:

Fruit GetFruit(String fruitName) { 
    if(fruitName == "apple") return Fruit("apple"); 
    else if(fruitName == "banana") return Fruit("banana"); 
    else fruit = return Fruit("kumquat"); //'cause who really wants to eat a kumquat? 
} 
... ve direkt haritalama bir (tercihen "akıllı") işaretçi kullanmak olacaktır:

auto_ptr<Fruit> GetFruit(String fruitName) { 
    auto_ptr<Fruit> fruit; 
    if(fruitName == "apple") fruit = new Fruit("apple"); 
    else if(fruitName == "banana") fruit = new Fruit("banana"); 
    else fruit = new Fruit("kumquat"); //'cause who really wants to eat a kumquat? 
    return fruit; 
} 
+1

Java, nondeterministic çöp toplama kullandığı için doğrudan bir eşleme oldukça zordur, oysa auto_ptr, sahiplik aktarımı anlamını ve ham işaretçileri kullanır. Hiç bellek yönetimi kullanmayın. Biraz daha az şaşırtıcı olabilecek bir varyasyon, "shared_ptr" gibi referans sayılan bir işaretçidir. 3 numara için – Philipp

1

++ Java örtülü olan işaretçiler vardır. Eğer bu sınıfın bir nesne için bir başvuru oluştururken

MyClass name; 

yazarken çünkü Java'da , sen açıkça bir nesne oluşturmak gerekir. Bu, adın gerçek nesne adresini içeren küçük bir bellek konumunu tanımladığı anlamına gelir. Tüm evi yeni kullanarak oluşturduğunuzda, yalnızca bu küçük bellek konumuna atanan adresi döndürür.

C++ bellek daha iyi kontrol var ve bir nesne oluşturma 2 yolu vardır: Eğer

MyClass object; 

Bu nesne yığınında oluşturulan deyimi kullanırsanız . Bu, işlev döndüğünde, nesnenin yok olduğu anlamına gelir. Yeni operatör kullanılmadan nesnenin otomatik olarak oluşturulduğunu unutmayın. Eğer yığın imha inat bir nesneyi isterseniz, yeni oluşturulan nesneye bir işaretçi döndürür yeni operatörünü kullanacağız:

MyClass *objectPtr = new MyClass(); 

* sınıf adından sonra yerleştirilen, sen istediğini gösterir Bu nesnenin bir tahsisatı yerine göreceli işaretçi türü. Böyle yapabilirsiniz Yani

delete objectPtr; 

:

MyClass *yourfunction(bool param) { 
    if (param) 
     return new MyClass(A); 
    return new MyClass(B); 
} 

Eğer bir bellek sızıntısı artık nesne gerekmez, ya da orada olacak zaman hafızasını temizlemek zorunda unutmayın

Yine de, Pointer'ların hiç güvenli olmadığını bileceksiniz! Kullanıcı kontrolünü işaretçiler üzerinden vermek kötü bir koda, kötü uygulamalara ve iyi olmayan şeylere yol açabilir. Hemen örnek: nesne kullanımından sonra belleği temizlemeyi unutursanız ne olur?)

Bu durumda akıllı işaretçiler kullanırsanız daha iyi, ama şimdi söylemek için gerçekten çok fazla şey var :) Googling tadını çıkarın!

0

Nesne C vs Java biraz farklı çalışır HIH ++. Sizin de belirttiğiniz gibi, kodunuzda varsayılan olarak bir nesne oluşturursunuz ve daha sonra etrafından geçme riskini üstlenirsiniz. Kodunuza değişim minimum hale getirmek için:

Fruit GetFruit(std::string fruitName) { 
    if(fruitName != "apple" && fruitName != "banana") 
    { 
     fruitName = "kumquat"; 
    } 
    return Fruit(fruitName); 
} 

Ancak bu kod nesnenin kendisi (iç verilerin tümünü dahil) yanı sıra eğer, karşılığında kopyalanan sonuçlanacaktır onun ileri etrafında kopyalanan kullanın.

Daha fazla Java esque olmak için bunun yerine boost::shared_ptr kullanırsınız. Daha sonra Java'da olduğu gibi referans sayılan bir nesne ile uğraşıyorsunuz:

boost::shared_ptr<Fruit> GetFruit(std::string fruitName) { 
    if(fruitName != "apple" && fruitName != "banana") 
    { 
     fruitName = "kumquat"; 
    } 
    return new Fruit(fruitName); 
}