Kopyalama yapıcısındaki özel değişkenlere neden erişebilirim?


88

Özel bir değişkene asla erişemeyeceğimi, sadece sınıfta bir get-işlevi ile öğrendim. Ama o zaman neden kopya yapıcısında ona erişebilirim?

Misal:

Field::Field(const Field& f)
{
  pFirst = new T[f.capacity()];

  pLast = pFirst + (f.pLast - f.pFirst);
  pEnd  = pFirst + (f.pEnd - f.pFirst);
  std::copy(f.pFirst, f.pLast, pFirst);
}

Beyannamem:

private:
  T *pFirst,*pLast,*pEnd;

Çünkü kopya yapıcı, varsayılan olarak bir sınıf üyesidir ve diğerleri de öyledir.
DumbCoder

+ 53 / -0? Buna kim oy verdi? Onları başka nasıl kopyalarsınız ?!? (Alternatif olmayanları çürütelim: Her özel üye için herkese açık bir referans toplayıcı yapalım mı? O zaman hiç özel değiller. const&Her biri için bir genel veya değer toplayıcı mı yapacaksınız? O zaman sadece 'özel' olurlar ve Değerler için kaynakları israf eder ve kopyalanamayan üyeler için başarısız olur.) Böyle anlamsız bir sorunun bu kadar başarılı olmasından şaşkınım, ne anlama geldiğini tamamen görmezden gelirken kopya oluşturma hakkında sorular soruyor ve hiçbir yanıt bunu çürütmek için temel mantığı kullanmıyor. Kuru teknik özellikleri açıklıyorlar, ancak bu kadar göz kırpan bir soruya çok daha basit bir cevap var
altçizgi_d

9
@underscore_d, "Bunları başka nasıl kopyalarsınız?" bence çok garip bir cevap. "Yerçekimi nasıl çalışır?" "başka nasıl düşebilirdi!" Nesne düzeyinde kapsülleme ile kafa karıştırıcı sınıf düzeyinde kapsülleme aslında oldukça yaygındır. Bunun aptalca bir soru olduğunu ve cevabın açık olması gerektiğini düşünmeniz komik. Smalltalk'taki kapsüllemenin (muhtemelen arketipsel OO dili) aslında nesne düzeyinde çalıştığını unutmayın.
aioobe

@aioobe İyi nokta, teşekkürler. Yorumum biraz aşırı - belki de kahve makinesi o gün bozulmuştu. Özellikle diğer (ve belki de daha fazla) OO dillerinden gelenler arasında, bu sorunun neden popüler olduğuna işaret ettiğiniz için teşekkür ederim. Aslında, yorumumun "göz kırpan" şey olduğu tartışılabilir, çünkü çoğunlukla C ++ dilinde program yapan birinin bakış açısından yazıyordum. Ayrıca, bu yerçekimi benzetmesini sevin!
underscore_d

Yanıtlar:


33

IMHO, mevcut cevaplar bunun "Nedenini" açıklamakta yetersiz kalıyor - hangi davranışın geçerli olduğunu yinelemeye çok fazla odaklanarak. "erişim değiştiriciler nesne düzeyinde değil, sınıf düzeyinde çalışır." - Evet ama neden?

Buradaki kapsayıcı kavram, bir sınıfı tasarlayan, yazan ve sürdüren programcı (lar) ın, istenen ve uygulanmasını koordine etmek için yetkilendirilmiş OO kapsüllemesini anlaması beklenen (s) olmasıdır. Yani, yazıyorsanız class X, yalnızca tek bir X xnesnenin ona erişimi olan kod tarafından nasıl kullanılabileceğini değil, aynı zamanda nasıl kullanılacağını da kodluyorsunuz :

  • türetilmiş sınıflar onunla etkileşim kurabilir (isteğe bağlı olarak saf sanal işlevler ve / veya korumalı erişim yoluyla) ve
  • farklı Xnesneler , tasarımınızdaki post-koşulları ve değişmezleri onurlandırırken amaçlanan davranışları sağlamak için işbirliği yapar.

Bu sadece kopya oluşturucu da değil - çok sayıda işlem sınıfınızın iki veya daha fazla örneğini içerebilir: karşılaştırma, ekleme / çarpma / bölme, kopyalama-oluşturma, klonlama, atama vb. ya sadece diğer nesnedeki özel ve / veya korunan verilere erişime sahip olmalı ya da daha basit, daha hızlı ya da genel olarak daha iyi bir işlev uygulamasına izin vermesini istemelidir.

Özellikle, bu işlemler aşağıdakiler gibi şeyler yapmak için ayrıcalıklı erişimden yararlanmak isteyebilir:

  • (kopya oluşturucular) bir başlatıcı listesindeki "rhs" (sağ taraf) nesnesinin özel bir üyesini kullanır, böylece bir üye değişkeni varsayılan olarak yapılandırılmış (yasal olsa bile) yerine kopyalanarak yapılandırılır ve sonra da atanır (yine, yasal ise)
  • kaynakları paylaş - dosya tanıtıcıları, paylaşılan bellek bölümleri, shared_ptrreferans verilere vb.
  • şeylerin sahipliğini almak, örneğin auto_ptr<>sahipliği yapım aşamasındaki nesneye "taşımak"
  • yeni nesneyi sıfırdan yeniden oluşturmak zorunda kalmadan en iyi şekilde kullanılabilir durumda oluşturmak için gereken özel "önbellek", kalibrasyon veya durum üyelerini kopyalayın
  • kopyalanmakta olan nesnede tutulan tanılama / izleme bilgilerini kopyala / bunlara erişim, aksi halde genel API'ler aracılığıyla erişilemez, ancak daha sonraki bir istisna nesnesi veya günlüğe kaydetme tarafından kullanılabilir (örneğin, "orijinal" kopyalanmamış olan "orijinal" kopyalanmamış örneğin zaman / koşullar hakkında bir şey inşa edildi)
  • bazı verilerin daha verimli bir kopyasını gerçekleştirin: örneğin, nesneler örneğin bir unordered_mapüyeye sahip olabilir, ancak yalnızca kamuya açık begin()ve end()yineleyiciler olabilir - size()size doğrudan erişim ile reservedaha hızlı kopyalama kapasitesi olabilir ; daha da kötüsü onlar sadece teşhir eğer at()ve insert()aksi ve throw....
  • Referansları bilinmeyen veya istemci kodu için salt yazılabilen üst / koordinasyon / yönetim nesnelerine geri kopyalayın

2
Bence en büyük 'neden', erişim değiştiricilerin nesne düzeyinde çalışıp çalışmadığını this == otherher eriştiğinizde kontrol etmenin muazzam bir çalışma zamanı ek yükü other.xolacağıdır.
aioobe

2
@aioobe Cevabınızın çok daha belirgin olması gerektiğini düşünüyorum. Tony'nin cevabı gerçekten iyi ve kavramsal olsa da, eğer bahis yapan bir adam olsaydım, cevabınızın seçim için gerçek tarihsel neden olduğuna bahse girerim. Sadece daha performanslı değil, aynı zamanda çok daha basit. Bjarne için harika bir soru olurdu!
Nir Friedman

Ben arka plan açıklıyor, çünkü cevap işaretlediğiniz;)
demonking

@demonking, bence bu cevapta verilen nedenler , özel verilerin diğer nesnelere açık olmasına izin vermenin neden uygun olduğunu kapsıyor . Ancak erişim değiştiriciler, verileri yeterince "açık bir şekilde" yapma anlamına gelmez. Daha ziyade , kapsülleme için verileri yeterince kapatmayı amaçlamaktadırlar . ( Kolaylık açısından, özel değişkenlerin kamuya açık olması daha da iyi olurdu!) Cevabımı, gerçek nedene daha iyi hitap ettiğini düşündüğüm bir bölümle güncelledim .
aioobe

@aioobe: eski yorumlar, ama her neyse ... " this == otherher eriştiğinizde kontrol edin other.x" - noktayı kaçırır - other.xyalnızca eşdeğer olduğunda çalışma zamanında kabul edilseydi , ilk etapta this.xçok fazla işaretçi yazma olmazdı other.x; derleyici sizi if (this == other) ...this.x...ne yapacaksanız onu yazmaya da zorlayabilir . Sizin "kolaylık (özel değişkenler kamu were daha varsa)" anlayışı da noktasını özlüyor - yolu izin Standard'ın olduğunu tanımlanmış kısıtlayıcı yeterince düzgün kapsülleme, ancak gereksiz yere rahatsız edici.
Tony Delroy

109

Erişim değiştiricileri , nesne düzeyinde değil, sınıf düzeyinde çalışır .

Yani, aynı sınıftaki iki nesne birbirinin özel verilerine erişebilir.

Neden:

Öncelikle verimlilik nedeniyle. Erişim değiştiricilerin nesne düzeyinde çalışıp çalışmadığını this == otherher eriştiğinizde kontrol etmek ihmal edilemez bir çalışma zamanı ek yükü other.xolacaktır.

Ayrıca, kapsam belirleme açısından düşünürseniz, anlamsal olarak mantıklıdır: "Özel bir değişkeni değiştirirken kodun ne kadar büyük kısmını aklımda tutmam gerekir?" - Tüm sınıfın kodunu aklınızda tutmanız gerekir ve bu, çalışma zamanında hangi nesnelerin var olduğu ortogonaldir.

Ve kopya oluşturucular ve atama operatörleri yazarken inanılmaz derecede kullanışlıdır.


35

Bir sınıfın özel üyelerine, sınıfın içinden, hatta başka bir örneğin özel üyelerine erişebilirsiniz.


10

Cevabı anlamak için size birkaç kavramı hatırlatmak isterim.

  1. Kaç tane nesne yaratırsanız oluşturun, o sınıf için bellekte bir işlevin yalnızca bir kopyası vardır. Bu, işlevlerin yalnızca bir kez oluşturulduğu anlamına gelir. Ancak değişkenler, sınıfın her bir örneği için ayrıdır.
  2. this işaretçi çağrıldığında her işleve aktarılır.

Şimdi, thisişaretçi sayesinde, işlev bu belirli örneğin değişkenlerini bulabilir. kamuya özel olup olmadığı önemli değil. bu işlevin içinden erişilebilir. Şimdi aynı sınıftaki başka bir nesneye bir işaretçi iletirsek. bu ikinci işaretçiyi kullanarak özel üyelere erişebileceğiz.

Umarım bu, sorunuzu yanıtlar.


6

Copy constructor, sınıfın üye işlevidir ve bu nedenle, "özel" olarak bildirilenler bile sınıfın veri üyelerine erişime sahiptir.


4
Dili bilen biri olarak ne demek istediğini anlıyorum. Bununla birlikte, dili bilmeseydim, soruyu bana tekrar tekrarladığını düşünürdüm.
San Jacinto
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.