2011-04-24 8 views
13

जब मैं सी ++ की बात करता हूं तो मैं बहुत नाराज हूं, ऑब्जेक्ट लौटने का बेहतर तरीका क्या है? मैं स्क्रिप्टिंग दुनिया से आ रहा हूं जहां ऑब्जेक्ट्स हमेशा संदर्भ होते हैं, और मैं एक ही धारणा को प्राप्त करने की कोशिश कर रहा हूं ... मैं When to pass by reference and when to pass by pointer in C++? से इसे बंद कर रहा हूं, जहां एक उपयोगकर्ता ने कहा: "अंगूठे का एक अच्छा नियम:" संदर्भों का उपयोग करें जब आप "।" कर सकते हैं तो आप कर सकते हैं और पॉइंटर्ससी ++ में किसी ऑब्जेक्ट को वापस करने का सबसे अच्छा तरीका?

Channel channel = layer.getChannel(); // creates a copy BAD 

जब यह होना चाहिए::

Channel &channel = layer.getChannel(); // reference good 

वहाँ की एक फोन करने वाले को लागू करने का कोई तरीका है

// basic layer class 
class Layer { private: Channel channel; // NEVER NULL }; 

// return object by pointer 
Channel *Layer::getChannel() { 
    return &channel; 
}; 

// return by reference 
Channel& Layer::getChannel() { 
    return channel; 
}; 

दूसरे संस्करण के साथ समस्या यह है कि संकलक इस लाइन स्वीकार करेगा दूसरा विकल्प बनाने के लिए इसे मजबूर करने का दूसरा विकल्प, या फिर पहला विकल्प बेहतर है, भले ही यह कभी भी न हो?

+9

"मैं पटकथा दुनिया में जहां वस्तुओं हमेशा संदर्भ हैं से आ रहा हूँ, और एक ही धारणा हासिल करने की कोशिश कर रहा हूँ" क्यों आप के आसपास सी ++ में संदर्भ के रूप में सब कुछ पारित करने के लिए कोशिश कर रहे हैं? सी ++ में ऐसा करना स्वाभाविक नहीं है। आपके द्वारा उद्धृत "अंगूठे का नियम" शायद बेहतर होगा "जहां भी संभव हो मूल्यों (और प्रतियां) का उपयोग करें, अन्यथा संदर्भों का उपयोग करें, और केवल अंतिम उपाय उपयोग पॉइंटर्स के रूप में।" –

+0

अपनी पृष्ठभूमि को ध्यान में रखते हुए, मैं दृढ़ता से सुझाव दूंगा कि आप ** स्मार्ट पॉइंटर्स ** के बारे में जानेंगे ताकि आपको ढेर-आवंटित वस्तुओं के लिए स्वचालित मेमोरी प्रबंधन मिल सके। –

उत्तर

11

आप इतना है कि यह copyable नहीं है Channel वर्ग खुद को समायोजित करने की जरूरत है। यदि यह कॉपी करने योग्य है, तो उपयोगकर्ता इसे कॉपी कर सकता है, और आप जो भी नहीं करते हैं उसे रोक सकते हैं।

यदि प्रतिलिपि एक सार्थक ऑपरेशन नहीं है, तो आप इसे "अक्षम" कर सकते हैं। बस कॉपी करने के लिए कॉपी कन्स्ट्रक्टर (Channel(const Channel&)) और असाइनमेंट ऑपरेटर (Channel& operator=(const Channel&)) को परिभाषित करें। फिर कक्षा की प्रतिलिपि बनाने के किसी भी प्रयास के परिणामस्वरूप संकलन त्रुटि होगी।

एक तरफ ध्यान दें पर, के रूप में दूसरों का उल्लेख किया है, सी ++ पटकथा भाषाओं जिससे आप परिचित हैं नहीं है। सब कुछ एक संदर्भ नहीं है, और आप केवल अन्यथा नाटक करके दर्द की दुनिया के लिए खुद को स्थापित कर रहे हैं। सी ++ में, स्टैक पर ऑब्जेक्ट्स आवंटित करना आम है, और संदर्भों और पॉइंटर्स को पास करने के बजाए वस्तुओं को मूल्य से पास करना आम है।

4

एक संदर्भ (या कॉन्स्ट संदर्भ) लौटने के लिए कॉलर को सदस्य चर के लिए सीधे पहुंच देने के लिए गेटटर विधि का सामान्य तरीका है, इसलिए मैं getChannel() के दूसरे संस्करण की अनुशंसा करता हूं।

यदि आप कॉलर्स को Channel की अनुपयुक्त प्रतिलिपि बनाने से रोकना चाहते हैं, तो आप इसकी प्रतिलिपि बनाने वाले को निजी बनाकर पूरा कर सकते हैं। (यदि आप प्रतियां बनाने से सब कुछ को रोकना चाहते हैं, यहां तक ​​कि Channel स्वयं भी, आप कन्स्ट्रक्टर को निजी घोषित कर सकते हैं और फिर इसे कार्यान्वित नहीं कर सकते हैं।) लेकिन आपको केवल यह करना चाहिए यदि प्रतिलिपि बनाना वास्तव में गैरकानूनी होगा, उदा। यदि वर्ग किसी अंतर्निहित संसाधन का प्रतिनिधित्व करता है जिसे कॉपी नहीं किया जा सकता है। कॉपी करने से इनकार न करें क्योंकि आपको लगता है कि कॉलर को की आवश्यकता नहीं है; वह कॉलर का निर्णय लेने का निर्णय है।

2

कॉपी करने पर आपके ऑब्जेक्ट की एक प्रति वापस लौटें, जब आपके उद्देश्यों के लिए महंगा नहीं है, और जब आपको मूल को बदलने में सक्षम होने की आवश्यकता नहीं है। यह डिफ़ॉल्ट होना चाहिए। संदर्भ या सूचक द्वारा

Channel Layer::getChannel() {  return channel; }; 

वापसी जब नकल महंगा है या आप मान बदलने के लिए चाहते हो सकता है जब। संदर्भ द्वारा लौटने से आप इस तरह की चीजों को कर सकते हैं:

layer.getChannel().clear(); 

और यह उस परत में मौजूद चैनल पर कार्य करता है।

एक पॉइंटर लौटने पर एक संदर्भ लौटने के समान ही है, सिवाय इसके कि यह आपको थोड़ा अधिक लचीलापन देता है, जिसमें पॉइंटर किसी ऑब्जेक्ट को पॉइंटर नहीं कर सकता है। मैं अक्सर एक सूचक जब मैं किसी अन्य वर्ग में "चैनल" स्टोर का उपयोग करने में सक्षम होना चाहता हूं। मैं तो

class MyClass 
{ 
    // ... 
    void setChannel(Channel *pC) { m_pChannel = pC; } 
private: 
    Channel * m_pChannel; // pointer to a channel that came from layer 
} 
1

आप एक फोन करने वाले को रोक नहीं सकते एक नया उदाहरण भी बनाने के लिए जब आप सूचक-रिटर्न-संस्करण का उपयोग करना चाहते हैं।

Channel* channel = new Channel(*layer.getChannel()); 

मुझे पता है कि इस लक्ष्य को प्राप्त करने का एक तरीका है। (उदाहरण के लिए, चैनल के सीटीआर को निजी बनाना ताकि केवल स्थिर सदस्य कार्य हो या उसके मित्र कार्य इसे बना सकें।) हालांकि, मुझे नहीं लगता कि यह आपके प्रश्न का मुद्दा है।

मुद्दा यह है कि जब आप या तो संदर्भ या सूचक लौटने सदस्य समारोह कर रहे हैं, तो आप एक फोन करने वाले विकल्पों वह चयन कर सकते हैं वह यह प्रतिलिपि करने या संदर्भित करने के लिए चाहता है कि क्या देना है। साथ ही, आप केवल पढ़ने के लिए const जोड़ कर अपना इरादा अधिक स्पष्ट कर सकते हैं।

अपने मामले के लिए, मैं चैनल के रूप में संदर्भ-रिटर्न-संस्करण के लिए जाना चाहते हैं खाली नहीं रह सकती। यदि आप नहीं चाहते हैं कि वे सदस्य चर बदल दें, रिटर्न कॉन्स संदर्भ। याद रखें कि रिटर्न वैल्यू टाइप का फैसला करने का कोई भी सबसे अच्छा तरीका नहीं है क्योंकि यह उस पर निर्भर करता है जो आप कहना चाहते हैं। आशा करता हूँ की ये काम करेगा! :)

1

आप वस्तु, आप वस्तु के लिए वर्ग सीधी पहुँच के उपयोगकर्ताओं दे रहे हैं, और आप ऐसा करने के लिए जा रहे हैं, तुम क्यों वस्तु निजी बना रहे हैं के लिए एक संदर्भ के बाद से वापस लौट रहे हैं? बस इसे सार्वजनिक करें।

+0

मैं किसी अन्य ऑब्जेक्ट सेटिंग Layer.channel को रोकने की कोशिश कर रहा हूं। एक संदर्भ लौटने से मुझे लगता है कि कोई भी अभी भी एक नए चैनल के संदर्भ को सही सेट कर सकता है? मेरे सर में दर्द है। – ansiart

-1

सबसे महत्वपूर्ण आपके आस-पास के कोड के साथ पठनीयता को बनाए रखना महत्वपूर्ण है। "जब रोम में हो तो वैसा ही करो जैसा की रोमन करते हैं।" महत्वपूर्ण है। आप इसे एक बार लिखते हैं, लेकिन हर कोई जो आपके कोड को बनाए रखना है उसे पढ़ना है। तो अचानक अपने कोड के सभी आप के आसपास हर किसी की तुलना में अलग दिशा निर्देशों का पालन, इसका मतलब है कि वे पहली बार अपनी शैली यह पता लगाने की जरूरत है, तो यह पता लगाने आप क्या कर रहे ...

एक दृष्टिकोण मैं काम देखा है बहुत अच्छी तरह से बातों के लिए चीजें आप बदल सकते हैं और स्थिरांक संदर्भ के लिए संकेत कर रहा है तुम नहीं:

class Passenger { 
    ... 
}; 

class Car { 
public: 
    int speed() const { return speed_; } 
    void set_speed(int speed) { speed_ = speed; } 
    const Passenger& passenger() const { return pass_;} 
    Passenger* mutable_passenger() { return &pass_; } 

private: 
    int speed_; 
    Passenger pass_; 
}; 

इस वर्ग के ग्राहकों को कर सकते हैं:

const Passenger& pass = car.passenger(); // no copy, but don't need to deal with NULL ptrs. 

अन्य उत्तर सुझाव बनाने एक संकलन त्रुटि को कॉपी अच्छे रहे हैं।

संबंधित मुद्दे

 संबंधित मुद्दे