2012-10-10 10 views
5

Olası Çoğalt:
Members vs method arguments access in C++Çatışmalar

Ben x, y, width ve height gibi bazı üyesi vardır bir sınıf. onun kurucusuna, ben bunu yapmazdım:

A::A(int x, int y, int width, int height) 
{ 
    x = x; 
    y = y; 
    width = width; 
    height = height; 
} 

Bu gerçekten mantıklı değil ve g ++ ile derlenmiş zaman x, y, width ve height garip değerleri (ör -1405737648) olurlar.

Bu adlandırma çakışmalarını çözmenin en iyi yolu nedir?

+3

Euh, argüman adlarına bir 'a' ekleniyor mu? –

+0

' A :: A (int xa, int, int, geniş, int heighta) – corazza

+0

, zarif olmak istiyorsanız, * önceden * a, İngilizce belirsiz bir makale oluşturan: aX, aY, aWidth, aHaight' vb. Açıkçası, aynı tanımlayıcı aynı kapsamda iki farklı değişkene başvurmak için kullanılamaz. Cevabımı gör. –

cevap

17

Aynı isimlerle gayet başlatma listelerini kullanabilirsiniz:

A::A(int x, int y, int width, int height) : 
    x(x), 
    y(y), 
    width(width), 
    height(height) 
{ 
} 

alternatif aynı adlar kullanmayı istemiyorsanız, farklı adlar kullanmaktır.

//data members 
int x_; 
int y_; 
int width_; 
int height_; 
//constructor 
A::A(int x, int y, int width, int height) : 
    x_(x), 
    y_(y), 
    width_(width), 
    height_(height) 
{ 
} 

Ama önce öneriyle yanlış bir şey yok: Bazı Macar-notasyonu varyasyon akla gelen (Bunun için bazı nefreti alabilirsiniz).

+0

17.4.3.1.2/1: Altçizgi ile başlayan her ad, genel ad alanında bir ad olarak kullanılmak üzere uygulamaya ayrılmıştır. –

+0

@JohnDibling neden sadece makrolar için geçerli olduğunu düşündüm? Oh iyi ... sanırım eski kodlara baktığımda nefret edeceğim bir şey daha var ...: D –

+0

Macarca notasyonun nesi yanlış? ;) Aslında, bu aslında sadece bir ön ad, aslında Macar notasyonunun bir varyantı değil. –

2

Oluşturucunun başlatma listesini kullanarak sorunu önleyebilirsiniz, ancak veri üyeleri, örneğin, bir _ veya önde gelen bir m_, adlandırma için bir kuralı takip etmenizi öneririz. Aksi takdirde, özellikle x ve y gibi adlara sahip üyeleriniz varsa, ad çakışması olasılığınız yüksektir.

class A 
{ 
    public: 

    A(int x, int y, int width, int height) : x_(x), y_(y), with_(width), height_(height) {} 

    int x_; 
    int y_; 
    int width_; 
    int height_; 
}; 
+0

Sık sık bunu (arkadaki alt çizgi) kongre olarak gördüm - kökenini biliyor musunuz? Herhangi bir ipucu için teşekkürler. – Wolf

+0

this-> ayrıca yerel kapsamdan ayrılmanın harika bir yoludur. – partyd

5

aşağıdaki gibi, bu sorun this işaretçi kullanmaktır hitap eden belirli desen (tercih edilir başlatıcı listesi kullanılarak aksine) yapıcı metotta atamaları kullanmanız gerekiyorsa:

this->a = a; 
0

Yapıcı argümanlarının isimlerini değiştirebilirsiniz. Eğer o zaman başlatılmamış gerçek örnek değişkene bırakarak kendileri için yapıcı argümanları atıyorsanız

A::A(int x, int y, int width, int height) 
{ 
    x = x; 
    y = y; 
    width = width; 
    height = height; 
} 

yazarken sen sahte değerleri alıyoruz, neden bu.

ben önermek (ve yaygın kullanın) genel çözümü yapıcı yönteminin argümanları isimlerini değiştirmektir:

A::A(int x_initial, int y_initial, int width_initial, int height_initial) 
{ 
    x = x_initial; 
    y = y_initial; 
    width = width_initial; 
    height = height_initial; 
} 
+0

Evet, yaptığım buydu, ama "_initial" yerine "a" ekledim. – corazza

+0

@Bane ve bunun nesi var? –

+0

Eh, "çirkin" bir çözüm gibi görünüyor ve kurucularımı anlamamda yanlış bir şey olduğunu öne sürdüm ... – corazza

2

Mümkünse, bu başlatıcı listesi aracılığıyla veri üyeleri ayarlamanın daha iyi, Bu durumda, gölge üye isimlerinin argümanlarla ilgili bir problemi yoktur. Başka bir alternatif ise kurucunun gövdesinde this->foo = foo; kullanılmasıdır. Setters için benzer bir sorun var, ancak şimdi başlatıcı listesi çözümünü kullanamazsınız. this->foo = foo; ile takıldınız - ya da sadece argümanlar ve üyeler için farklı isimler kullanın.Bazı kişiler, gölge veri üyelerini gölgeleyen nefretlerden gerçekten nefret ederler; Birden çok kodlama standardı açıkça bunu asla yapmaz. Diğerleri ise bu tür bir gölgelendirmeyi düşünür, en azından kurucular ve ayarlayıcılar için, kedinin miyavıdır. Bir ya da iki kodlama standardını (ama hatırlatmıyorum), bu tür bir gölgelemeyi “yapmalı” (ama “olmaz”) pratiği olarak belirlediğimi hatırlıyorum. Bir son seçenek, okuyuculara işlevin ne yaptığına dair bir ipucu vermek, ancak uygulamadaki farklı isimleri kullanmak için işlev beyanındaki gölgelemeyi kullanmaktır.

Güncelleme: "Gölge" nedir?

#include <iostream> 

void printi (int i) { std::cout << "i=" << i << "\n"; } 

int i = 21; 

int main() { 
    printi (i); 
    int i = 42; 
    printi (i); 
    for (int i = 0; i < 3; ++i) { 
     printi (i); 
     int i = 10; 
     printi (i); 
    } 
    printi (i); 
} 

i, int i=10 en iç Bildirge ise sırayla küresel değişkeni i gölgeler fonksiyon kapsamı en bildirilen değişken i gölgeler for açıklamada, bildirilen değişken i gölgeler. sınıf A gölge için varsayılan olmayan kurucu el altında probleminde

, argümanlar x, y, width ve height fikir tartışmalarının aynı isimdeki üye verileri. Sizin width=width; Sayfanız width argümanı width veri üyesini gölgeler (gizler) nedeniyle hiçbir şey yapmadı. Farklı kapsamlarda bildirilen aynı ada sahip iki veya daha fazla değişkeniniz olduğunda, kazanan her zaman en içteki kapsamıdır. Genel olarak, her zaman kazanacak en içteki kapsamı olan isimdir.

+0

Tam olarak "gölgeleme" olarak adlandırdığınız şey nedir? – corazza

+0

@Bane - "gölgeleme" nedir? Göçmenlik: (1) CS 101 öğrencilerinin kapsam belirlemeyi anlamalarını test etmek için kullanılan bir işkence cihazı. (2) Bazı kapsamlarda bildirilen bir değişken, bazı dış alanda bildirilen değişkenle aynı ada sahip olduğunda. (3) Yapıcınızla yaptığınız şey. (4) '-Wshadow' ile derlenerek yakalanan potansiyel bir problem. (5) Güncellenmiş cevabımı görün. –

+0

Şimdi anlıyorum, teşekkürler! – corazza

İlgili konular