@SebastianRedl zaten basit, doğrudan cevapları verdi, ancak bazı ek açıklamalar faydalı olabilir.
TL; DR = yapıcıları basit tutmak için bir stil kuralı var, bunun sebepleri var, ama bu nedenler çoğunlukla tarihi (veya sadece kötü) bir kodlama stiliyle ilgilidir. Yapıcılarda istisnaların işlenmesi iyi tanımlanmıştır ve yıkıcılar hala tamamen inşa edilmiş yerel değişkenler ve üyeler için çağrılacaktır, yani deyimsel C ++ kodunda herhangi bir sorun olmamalıdır. Stil kuralı yine de devam eder, ancak normalde bu bir sorun değildir - tüm başlatmalar kurucuda olmak zorunda değildir ve özellikle bu kurucu olmak zorunda değildir.
Bu , yapıcıların tanımlanmış bir geçerli durum oluşturmak için ellerinden gelenin en iyisini yapmaları gereken yaygın bir stil kuralıdır . İlklendirmeniz daha karmaşıksa, yapıcının dışında kullanılmalıdır. Yapıcınızın ayarlayabileceği ucuz bir başlangıç değeri yoksa, bir tane eklemek için sınıfınızın zorladığı işgalcileri zayıflatmalısınız. Örneğin, sınıfınızın yönetmesi için depolama alanı ayırmak çok pahalıysa, elbette null gibi özel durum durumlarının hiç kimsenin soruna neden olmadığından tahsis edilmemiş ancak boş bir durum ekleyin. Ahem.
Yaygın olmasına rağmen, kesinlikle bu aşırı biçimde mutlak olmaktan çok uzak. Özellikle, alayımın da belirttiği gibi, işgalcileri zayıflatmanın neredeyse her zaman çok yüksek bir fiyat olduğunu söyleyen kamptayım. Ancak, stil kuralı arkasında nedenler vardır, ve minimal kurucular ikisine de sahip yolları var ve güçlü değişmezleri.
Sebepler, özellikle istisnalar karşısında otomatik yıkıcı temizliği ile ilgilidir. Temel olarak, derleyici yıkıcıları çağırmaktan sorumlu olduğunda iyi tanımlanmış bir nokta olmalıdır. Hala bir yapıcı çağrısındayken, nesne mutlaka tam olarak oluşturulmuş değildir, bu nedenle bu nesneye yönelik yıkıcıyı çağırmak geçerli değildir. Bu nedenle, nesneyi imha etme sorumluluğu yalnızca yapıcı başarıyla tamamlandığında derleyiciye geçer. Bu, gerçekten en iyi isim olmayan RAII (Kaynak Tahsisi Başlatılıyor) olarak bilinir.
Yapıcı içinde bir istisna atması meydana gelirse, kısmen yapılmış herhangi bir şeyin, tipik olarak a try .. catch
.
Ancak, başarılı bir şekilde inşa edilmiş olan nesnenin bileşenleri zaten derleyicilerin sorumluluğundadır. Bu, pratikte bunun gerçekten önemli bir şey olmadığı anlamına gelir. Örneğin
classname (args) : base1 (args), member2 (args), member3 (args)
{
}
Bu yapıcının gövdesi boş. Yani uzun süre kurucular olarak base1
, member2
ve member3
istisna güvenli, endişelenecek bir şey yok. Örneğin, eğer bir kurucu member2
fırlatırsa, bu kurucu kendini temizlemekten sorumludur. Taban base1
zaten tamamen inşa edildi, bu yüzden yıkıcısı otomatik olarak çağrılacak. member3
hiç bir zaman bile kısmen inşa edilmedi, bu yüzden de temizlenmesi gerekmiyor.
Bir ceset varken bile, istisna atılmadan önce tamamen oluşturulan yerel değişkenler, diğer işlevler gibi otomatik olarak imha edilir. Ham işaretçilerle hokkabazlık yapan veya "kendi" bir tür örtülü durumun (başka yerde saklanan) "tipik" bir başlatma / alma işlevi çağrısının bir son / bırakma çağrısıyla eşleştirilmesi gerektiği anlamına gelen yapıcı organlar istisna güvenlik sorunlarına neden olabilir bir kaynağı bir sınıf aracılığıyla doğru şekilde yönetemiyor. Örneğin, ham işaretçileri unique_ptr
kurucu ile değiştirirseniz , gerekirse yıkıcı unique_ptr
otomatik olarak çağrılır.
İnsanların en az yapıcıları tercih etmeleri için verdikleri başka nedenler var. Birincisi, stil kuralının var olmasından dolayı, çoğu insan yapıcı çağrılarının ucuz olduğunu varsayar. Buna rağmen hala güçlü değişmezlere sahip olmanın bir yolu, bunun yerine zayıflamış değişmezlere sahip olan ve (potansiyel olarak birçok) normal üye işlev çağrıları kullanarak gerekli başlangıç değerini ayarlayan ayrı bir fabrika / üretici sınıfına sahip olmaktır. İhtiyacınız olan başlangıç durumuna sahip olduğunuzda, bu nesneyi güçlü değişmezlerin bulunduğu sınıfın yapıcısına argüman olarak iletin. Bu zayıf değişmez nesnenin "bağırsaklarını çalabilir" - anlamsallığı taşıyor - ki bu ucuz (ve genellikle noexcept
) bir işlemdir.
Ve elbette bunu bir make_whatever ()
fonksiyona sarabilirsiniz , böylece bu işlevin arayanları asla zayıflamış değişmez sınıf örneğini görmek zorunda kalmazlar.