2012-10-24 28 views
9

Temel sınıfım varsa, yalnızca sanal yöntemleri ve temel sınıfını kullanarak bu sanal yöntemlerle bir temel sınıfım varsa.Temel sınıf dizisini işaret eden türetilmiş sınıfla doldurun

Nasıl yapılır:

// causes C2259 
BaseClass* base = new BaseClass[2]; 

BaseClass[0] = new FirstDerivedClass; 
BaseClass[1] = new SecondDerivedClass; 

ya:

// causes "base is being used without being initialized" 
BaseClass* base; 
// causes CC59 again 
BaseClass* base = new BaseClass; 

base[0] = FirstDerivedClass(); 
base[1] = SecondDerivedClass(); 

(veya benzeri)

... Ben DerivedClass aracılığıyla BaseClass s yöntemleri erişebileceği şekilde, ama işaretçi ve işaretçi DerivedClass s dizisidir?

cevap

8

Kişisel dizi yanlış türde şudur: BaseClass nesneyi saklar örnekleri, işaretçisi yerine örneğidir. BaseClass, özet gibi göründüğünden, derleyici, dizininizi doldurmak için örnekleri varsayılan olarak yapılandıramadığından şikayetçidir.

BaseClass özet olmasa bile, polimorfik dizileri C++ 'da bir big no-no kullanarak her durumda farklı bir şey yapmalısınız. kod değiştirerek

Fix: bahsedilen

BaseClass** base = new BaseClass*[2]; 

BaseClass[0] = new FirstDerivedClass; 
BaseClass[1] = new SecondDerivedClass; 

, çoğu zaman yerine aptal işaretçiler yerine düz diziler ve (örneğin std::shared_ptr gibi) akıllı işaretçileri std::vector kullanımı tercih edilir. El ile kod yazmak yerine bu araçları kullanmak, son derece küçük bir çalışma zamanı maliyetinde şeffaf bir şekilde sorunları barındırır. senin AnaSınıf saf sanal yöntemleri içeriyorsa

+1

"Nesne dilimleme" olarak adlandırılan sorun, dizilere özgü değildir - türetilmiş bir sınıfı bir temel sınıfa * değer * atadığınız her zaman oluşur. Örneğin. 'BaseClass b; b = FirstDerivedClass(); 'yine de sessizce kıran (ancak en iyi ihtimalle bir derleyici uyarısı alabilirsiniz) C++ ile karşılaştırılabilir. –

+0

Link taşınmış görünüyor. – user6003859

+1

@ user6003859 Güncelleme yaptım, teşekkürler! – Jon

3

O C yerine basit dizinin std::vector kullanmak ++ geçerli: en güvenli yöntem kullanmaktır fark

std::vector<BaseClass*> base; 
base.push_back(new FirstDerivedClass()); 
base.push_back(new SecondDerivedClass()); 

Kerrek SB gibi std::unique_ptr:

std::vector<std::unique_ptr<BaseClass> > base; 
base.push_back(std_unique_ptr<BaseClass>(new FirstDerivedClass())); 
base.push_back(std_unique_ptr<BaseClass>(new SecondDerivedClass())); 
+2

Ama bir dizi istermiyim? – Deukalion

+1

Ne için? Hız? Güvenilirlik? –

+0

Ne hakkında: BaseClass * Base [2]; Base [0] = new FirstDerivedClass; Temel [1] = yeni SecondDerivedClass; – Al2O3

2

, bu derlemeye başarısız olur:

BaseClass* base = new BaseClass[2]; 

o bellek sızıntısı almak için gidiyoruz etmezse.

C++ uygulamasında, bu bir çeşit akıllı işaretçi ile std :: vector veya std :: array kullanılarak yapılır. Örneğin:

std::vector< std::shared_ptr<BaseClass> > arr(2); 
arr[0].reset(new FirstDerivedClass()); 
arr[1].reset(new SecondDerivedClass()); 
+0

OP'nin koduyla daha da önemli bir sorun, programları sessizce kesen * nesne dilimleme *. –

+0

@j_random_hacker Bu yüzden bir çeşit akıllı işaretçi kullanmayı önerdim. Taban tipindeki nesnelerin saklanması (eğer saf işlevlere sahip değilse), –

0

Bu

BaseClass* Base[2]; 

Base[0] = new FirstDerivedClass; 
Base[1] = new SecondDerivedClass; 
+1

dilimlemesine neden olur. Bu, orijinal kodunuzun yapmaya çalıştığı şeyden çok farklı * bir şey yapar. Bu dizi yığında tahsis edilirken, başlangıçta yığın üzerindeydi. – Jon

+0

Evet, sanırım. Şimdi dizi bir işaretçidir ve dizide işaretçiler vardır. – Deukalion

0

(Rubby itibaren) cevap gösterici bir dizi tanımlama olduğu, sivri tipte AnaSınıf olup. Ve işaretçiyi türetilmiş öğelere dizinin öğelerine atayın. sadece aşağıdaki gibi:

BaseClass* base [2]; 
base[0] = new FirstDerivedClass; 
base[1] = new SecondDerivedClass; 
İlgili konular