2012-10-10 26 views
5

संभव डुप्लिकेट:
Members vs method arguments access in C++संघर्ष

मैं एक वर्ग कुछ सदस्यों, x, y, width और height की तरह है। इसके निर्माता में, मैं यह करना होगा नहीं:

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

यह वास्तव में कोई मतलब नहीं है और जब जी के साथ ++ संकलित x, y, width, और height अजीब मान (उदा -1405737648) हो जाते हैं।

इन नामकरण विवादों को हल करने का सबसे अच्छा तरीका क्या है?

+3

ईह, तर्क नामों के लिए 'ए' जोड़ना? –

+0

'ए :: ए (इंट xa, int ya, int widtha, int heighta)' – corazza

+0

यदि आप सुरुचिपूर्ण होना चाहते हैं, * प्री * एक 'अनिवार्य लेख' बनाते हैं, एक अंग्रेजी अनिश्चित लेख बनाते हैं: 'anX, aY, aWidth, AHight' आदि जाहिर है, एक ही पहचानकर्ता को एक ही दायरे में दो अलग-अलग चर के संदर्भ में उपयोग नहीं किया जा सकता है। मेरा जवाब देखें –

उत्तर

17

आप प्रारंभ सूचियों में एक ही नाम के साथ ठीक उपयोग कर सकते हैं:

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

एक वैकल्पिक, अलग-अलग नाम का उपयोग करने के लिए यदि आप एक ही नाम है नहीं करना चाहती है। कुछ हंगरी अंकन भिन्नता मन में आता है (मैं इस के लिए कुछ नफरत हो सकती है):

//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) 
{ 
} 

लेकिन वहाँ पहला सुझाव के साथ कुछ भी गलत नहीं है।

+0

17.4.3.1.2/1: अंडरस्कोर से शुरू होने वाला प्रत्येक नाम वैश्विक नामस्थान में नाम के रूप में उपयोग के लिए कार्यान्वयन के लिए आरक्षित है। –

+0

@ जॉन डीबलिंग मुझे क्यों लगता है कि केवल मैक्रोज़ पर लागू होता है? ओह ठीक है ... अनुमान लगाओ कि जब मैं पुराने कोड पर वापस देखता हूं तो मुझे नफरत होगी ...: डी –

+0

हंगेरियन नोटेशन के साथ क्या गलत है? ;) हालांकि, यह वास्तव में सिर्फ एक उपसर्ग नाम है, वास्तव में हंगेरियन नोटेशन का एक संस्करण नहीं है। –

2

हालांकि आप कन्स्ट्रक्टर की प्रारंभिक सूची का उपयोग करके समस्या से बच सकते हैं, उदाहरण के लिए, मैं डेटा सदस्यों का नामकरण करने के लिए एक सम्मेलन का पालन करता हूं, उदाहरण के लिए, पिछला _, या एक अग्रणी m_। अन्यथा आपको नाम संघर्ष होने की संभावना है, विशेष रूप से यदि आपके पास x और y जैसे नाम वाले सदस्य हैं।

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

मैंने अक्सर यह (पिछला अंडरस्कोर) सम्मेलन देखा - क्या आप इसकी उत्पत्ति जानते हैं? किसी भी संकेत के लिए धन्यवाद। – Wolf

+0

यह-> स्थानीय दायरे से अलग होने का भी एक शानदार तरीका है। – partyd

5

, इस मुद्दे this सूचक का उपयोग करना है पता करने के लिए विशेष पैटर्न (के रूप में जो पसंद किया जाता है initializers की एक सूची का उपयोग कर के खिलाफ) इस प्रकार आप निर्माता में कार्य उपयोग करना आवश्यक है:

this->a = a; 
0

आप केवल कन्स्ट्रक्टर तर्कों के नाम बदल सकते हैं। जब आप

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

बारे में तो आप खुद को लिए निर्माता की तर्क बताए रहे हैं, अप्रारंभीकृत वास्तविक उदाहरण चर छोड़ रहा है, यही कारण है कि आप फर्जी मान हो रही है है।

सामान्य समाधान मेरा सुझाव है (और व्यापक रूप से उपयोग करें) निर्माता विधि के तर्कों का नाम बदलने के लिए है:

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

हाँ, मैंने यही किया, लेकिन "_initial" के बजाय मैंने "ए" जोड़ा। – corazza

+0

@ बेन और इसके साथ क्या गलत है? –

+0

वैसे यह एक "बदसूरत" समाधान प्रतीत होता है, और मुझे लगता है कि यह सुझाव दिया गया है कि रचनाकारों की मेरी समझ में कुछ गड़बड़ है ... – corazza

2

बिल्कुल संभव हो तो, यह प्रारंभकर्ता सूची के माध्यम से डेटा के सदस्यों सेट करने के लिए बेहतर है, जिस स्थिति में छाया सदस्य नामों के तर्कों के साथ कोई समस्या नहीं है। एक और विकल्प कन्स्ट्रक्टर के शरीर में this->foo = foo; का उपयोग करना है। सेटर्स के लिए एक समान समस्या मौजूद है, लेकिन अब आप प्रारंभकर्ता सूची समाधान का उपयोग नहीं कर सकते हैं। आप this->foo = foo; से फंस गए हैं - या केवल तर्क और सदस्यों के लिए अलग-अलग नामों का उपयोग करें।

कुछ लोग वास्तव में उन तर्कों से नफरत करते हैं जो डेटा सदस्यों को छाया करते हैं; एकाधिक कोडिंग मानक स्पष्ट रूप से ऐसा नहीं करते हैं। दूसरों को लगता है कि कम से कम रचनाकारों और सेटर्स के लिए, बिल्ली की मेयो है। मुझे याद है कि एक या दो कोडिंग मानकों को पढ़ना याद है (लेकिन मुझे याद नहीं है) जिसने इस तरह के छायांकन को "चाहिए" (लेकिन "नहीं") अभ्यास के रूप में नामित किया है।

एक अंतिम विकल्प फ़ंक्शन घोषणा में छायांकन का उपयोग करना है ताकि पाठकों को कार्य के बारे में संकेत मिले, लेकिन कार्यान्वयन में अलग-अलग नामों का उपयोग करें।

अद्यतन: "छायांकन" क्या है?

#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 के अंतरतम घोषणा, चर ifor बयान, जो बारी में चर i समारोह गुंजाइश, जो बारी में वैश्विक चर i छाया पर घोषित कर दिया छाया में घोषित छाया।

हाथ में समस्या में, तर्क x, y, width, और height वर्ग A छाया लिए गैर-सामान्य निर्माता करने के लिए उन तर्कों के रूप में एक ही नाम के साथ सदस्य डेटा।

आपके width=width; ने कुछ भी नहीं किया क्योंकि तर्क width डेटा सदस्य width तर्क (छुपाएं)। जब आपके पास अलग-अलग क्षेत्रों में घोषित किए गए एक ही नाम के साथ दो या दो से अधिक चर होते हैं, तो विजेता हमेशा सबसे निचले दायरे के साथ नाम होता है। आम तौर पर, यह हमेशा जीतने वाले सबसे निचले क्षेत्र के साथ नाम होता है।

+0

आप वास्तव में "छायांकन" के रूप में क्या कहते हैं? – corazza

+0

@बेन - "छायांकन" क्या है? छायांकन: (1) एक यातना उपकरण यह जांचने के लिए प्रयोग किया जाता है कि सीएस 101 के छात्र स्कॉइंग समझते हैं या नहीं। (2) जब किसी दायरे में घोषित एक चर के पास एक बाहरी नाम के रूप में घोषित वैरिएबल के समान नाम होता है। (3) आपने अपने कन्स्ट्रक्टर के साथ क्या किया। (4) एक संभावित समस्या जिसे '-Wshadow' के साथ संकलित करके पकड़ा जाता है। (5) मेरा अद्यतन उत्तर देखें। –

+0

अब मैं समझता हूं, धन्यवाद! – corazza