2010-07-20 15 views
5

के बजाय एक अनियमित प्लेसहोल्डर वैरिएबल बनाना अभी मैं जावा से सी ++ में जा रहा हूं और जब भी जावा में आमतौर पर उपयोग की जाने वाली अवधारणा सी ++ में मैप नहीं होती है तो मुझे कुछ कठिनाइयां होती हैं। उदाहरण के लिए, जावा में मैं की तरह कुछ करना होगा:सी ++: डिफ़ॉल्ट ऑब्जेक्ट

Fruit GetFruit(String fruitName) { 
    Fruit fruit; 
    if(fruitName == "apple") fruit = new Fruit("apple"); 
    else if(fruitName == "banana") fruit = new Fruit("banana"); 
    else fruit = new Fruit("kumquat"); //'cause who really wants to eat a kumquat? 

    return fruit; 
} 

बेशक सी में, ++ Fruit fruit; बयान वास्तव में एक फल पैदा करता है। क्या इसका मतलब है कि मुझे एक डिफ़ॉल्ट कन्स्ट्रक्टर होना है? यह असुरक्षित लगता है! क्या होगा यदि मेरा डिफ़ॉल्ट फल बच निकला?

+4

क्या होगा यदि डिफ़ॉल्ट फल बच निकला और शहर को आतंकित कर दिया जाए? नहीं, गंभीरता से, 'बच निकले' से आपका क्या मतलब है? –

+8

_ खूनी कुमक्वेट्स का एटैक!_ –

+2

एक और गंभीर नोट पर: [आपके पिछले प्रश्न] के जवाब में समाधानों में समस्या क्या है (http://stackoverflow.com/questions/3285970/c-and-returning-a-null-what-worked- इन-जावा-does not को-कार्य में ग)? मुझे लगता है कि मैं यह देखने में असफल रहा हूं कि उस प्रश्न के उत्तर इस सवाल का जवाब नहीं देते हैं। –

उत्तर

9

सी ++ आप बहुत कुछ देता है जब फल बनाने की बात आती है तो सिरदर्द। अपनी जरूरतों के आधार पर, आप निम्न विकल्पों में से एक चुन सकते हैं:

1) एक स्टैक पर एक फल बनाएं और एक प्रतिलिपि (आपको एक प्रतिलिपि बनाने की आवश्यकता है) लौटाएं और नाम के मामले में कुछ डिफ़ॉल्ट फल प्रदान करना चाहिए मैच:

Fruit GetFruit(const std::string &name) 
{ 
    if (name == "banana") return Fruit("banana"); 
    if (name == "apple") return Fruit("apple"); 
    return Fruit("default"); 
} 

2) एक ढेर पर एक फल बना सकते हैं और देखभाल, अशक्त-सूचक लौट आए हो सकता है कि और भी कहीं न कहीं इस फल को हटाने और देखभाल है कि यह केवल एक बार और केवल अपने द्वारा हटा दिया जाता है लेने के लिए याद मालिक (और ध्यान रखें कि हटाए गए फल में कोई भी सूचक नहीं है):

Fruit* GetFruit(const std::string &name) 
{ 
    if (name == "banana") return new Fruit("banana"); 
    if (name == "apple") return new Fruit("apple"); 
    return NULL; 
} 

3) और अंत में, कई संभावित सूचक समस्याओं से बचने के लिए एक स्मार्ट सूचक का उपयोग करें (लेकिन शून्य पॉइंटर्स का ख्याल रखें)।यह विकल्प आपके जावा प्रोग्रामिंग अनुभव के सबसे करीब है: वहाँ एक वस्तु के बीच एक अंतर (है कि स्मृति में एक इकाई है) और उसका पता है:

typedef boost::shared_ptr<Fruit> FruitRef; 

FruitRef GetFruit(const std::string &name) 
{ 
    if (name == "banana") return new Fruit("banana"); 
    if (name == "apple") return new Fruit("apple"); 
    return FruitRef(); 
} 
+0

नंबर 3 के लिए +1, shared_ptr उत्तर है, आपके अनुपालन में शायद बिना किसी बढ़ावा के कार्यान्वयन है क्योंकि shared_ptrs tr1 – Patrick

+5

में हैं 4. यदि आप गतिशील आवंटन से बचें तो 'boost :: वैकल्पिक 'का उपयोग करें। –

+0

@ माइक सेमुर। बूस्ट :: वैकल्पिक के बारे में कभी नहीं सुना। आपकी टिप्पणी के लिए धन्यवाद =) – SadSido

1

सी ++ में अपना उदाहरण मैप करने के लिए, आपको एक पॉइंटर का उपयोग करना चाहिए। सी ++ में, निर्मित ऑब्जेक्ट को वैध ऑब्जेक्ट माना जाता है (इसलिए, संदर्भ के साथ, आप शून्य नहीं कर सकते हैं)।

फल * फल = 0 का उपयोग करना; ...

आप अपनी आवश्यकता के लिए एक ऑब्जेक्ट डिफॉल्ट कर सकते हैं, या 0 टेस्ट पास होने पर डिफॉल्ट हो सकता है।

+1

क्या पॉइंटर दृष्टिकोण काफी मानक होगा? या यह किसी कारण से अजीब है? – JnBrymn

+1

@ जॉन: सूचक दृष्टिकोण मानक है। यह जावा प्रोग्रामर के लिए अजीब लग सकता है, लेकिन फिर जावा में ऐसी चीजें हैं जो सी ++ प्रोग्रामर के लिए अजीब लगती हैं। यदि आप सी ++ का उपयोग करने जा रहे हैं, तो आपको किसी प्रकार के पॉइंटर्स का उपयोग करने की आवश्यकता है। –

+0

यह बुरा नहीं है, लेकिन आपको बाद में पॉइंटर को हटाने की देखभाल करनी चाहिए। या आप एक स्मार्ट पॉइंटर का उपयोग कर सकते हैं (यह एक सूचक है जो संदर्भों की गणना करता है और जब कोई इसका उपयोग नहीं करता है तो खुद को हटा दें)। – Scharron

0

आपका fruit जावा में परिवर्तनीय मोटे तौर पर एक सी ++ पॉइंटर के लिए मानचित्र। आप सही हैं, आप स्टैक पर ऑब्जेक्ट नहीं बनाना चाहते हैं, आप बस उस नई ऑब्जेक्ट को पॉइंटर चाहते हैं जिसे आप बना रहे हैं। इसलिए यदि आप Fruit से Fruit* बदलते हैं तो यह काम करेगा (यदि आप फ़ंक्शन रिटर्न प्रकार भी बदलते हैं)। बस याद रखें कि आपको बाद में delete पॉइंटर को इस फ़ंक्शन से लौटाया जाना चाहिए, आपके new एस को साफ़ करने के लिए कोई कचरा संग्रह नहीं है।

6

जावा में ऑब्जेक्ट पॉइंटर्स द्वारा दर्शाए जाते हैं। चूंकि यह व्यापक है, पॉइंटर्स के लिए कोई विशेष संकेत नहीं है। सी ++ में, वस्तुओं को स्वयं या पॉइंटर्स द्वारा दर्शाया जा सकता है, इसलिए जब वे होते हैं तो पॉइंटर्स निर्दिष्ट करना आवश्यक है।

सी ++ अपने कोड का संस्करण है:

Fruit * GetFruit(std::string fruitName) { 
    Fruit * fruit = 0; 
    if (fruitname == "apple") fruit = new Fruit("apple"); 
    else if (fruitname == "banana") fruit = new Fruit("banana"); 
    else fruit = new Fruit("kumquat"); 

    return fruit; 
} 

यह Fruit के लिए सूचक देता है। आप fruit->color() जैसे सदस्यों तक पहुंचेंगे, fruit.color() नहीं। आपको delete होना चाहिए कि जब आप इसके साथ हों तो सूचक।

+1

ऑब्जेक्ट। साझा पॉइंटर्स के बराबर हैं। एक सूचक लौटने पर कोड गंध या सी कोड का संकेत होता है (मेरे लिए वही बात। :-) –

2

सबसे सरल तरीका होगा:

Fruit GetFruit(String fruitName) { 
    if(fruitName == "apple") return Fruit("apple"); 
    else if(fruitName == "banana") return Fruit("banana"); 
    else fruit = return Fruit("kumquat"); //'cause who really wants to eat a kumquat? 
} 

... और एक सीधा मानचित्रण एक (अधिमानतः "स्मार्ट") सूचक का उपयोग करने के होगा:

auto_ptr<Fruit> GetFruit(String fruitName) { 
    auto_ptr<Fruit> fruit; 
    if(fruitName == "apple") fruit = new Fruit("apple"); 
    else if(fruitName == "banana") fruit = new Fruit("banana"); 
    else fruit = new Fruit("kumquat"); //'cause who really wants to eat a kumquat? 
    return fruit; 
} 
+1

जावा प्रत्यक्ष नोडेटर्मिनिस्टिक कचरा संग्रह का उपयोग करता है, जबकि प्रत्यक्ष मैपिंग काफी कठिन है, जबकि 'auto_ptr' हस्तांतरण-ऑफ-स्वामित्व अर्थशास्त्र और कच्चे पॉइंटर्स का उपयोग करता है बिल्कुल मेमोरी प्रबंधन का उपयोग करें। एक संस्करण जो थोड़ा कम आश्चर्यजनक हो सकता है वह एक संदर्भ-गिनती सूचक है जैसे 'shared_ptr'। – Philipp

1

C++ में वहाँ संकेत है, जो जावा में निहित हैं। जावा में, आप, क्योंकि जब आप लिखना

MyClass name; 

आप उस वर्ग की एक वस्तु के लिए एक संदर्भ बना रहे हैं, स्पष्ट रूप से एक वस्तु बनाने के लिए की जरूरत है। इसका अर्थ यह है कि नाम एक छोटी स्मृति स्थान की पहचान करता है जिसमें वास्तविक वस्तु पता होता है। जब आप नए घर का उपयोग करके पूरे घर का निर्माण करते हैं, तो यह केवल उस पते को लौटाता है, जो उस छोटे स्मृति स्थान को सौंपा गया है।

C++ में स्मृति का एक बेहतर नियंत्रण नहीं है और आप एक वस्तु बनाने के 2 तरीके हैं: अगर आप बयान

MyClass object; 

इस वस्तु ढेर में बन जाता है का उपयोग करें। इसका मतलब है कि जब समारोह वापस आता है, वस्तु नष्ट हो जाती है। ध्यान दें कि नया ऑपरेटर उपयोग किए बिना ऑब्जेक्ट स्वचालित रूप से बनाया गया है। आप ढेर विनाश लागू करने के लिए एक वस्तु चाहते हैं, आप नए ऑपरेटर, जो नव निर्मित वस्तु के लिए सूचक रिटर्न का उपयोग करेगा:

MyClass *objectPtr = new MyClass(); 

* वर्ग के नाम के आगे रखें, मतलब है कि आप के लिए पूछ रहे हैं उस वस्तु के आवंटन के बजाय सापेक्ष सूचक प्रकार।

याद रखें कि आप स्मृति साफ करने के लिए जब आप वस्तु की आवश्यकता नहीं है, या नहीं होगा एक स्मृति रिसाव है:

delete objectPtr; 

तो, अगर आप इस तरह कर सकते हैं:

MyClass *yourfunction(bool param) { 
    if (param) 
     return new MyClass(A); 
    return new MyClass(B); 
} 

आपको पता चलेगा, वैसे भी, पॉइंटर्स सुरक्षित नहीं हैं! पॉइंटर्स पर उपयोगकर्ता नियंत्रण देने से खराब कोड, बुरी प्रथाएं और बहुत सी चीजें हो सकती हैं जो सभी में अच्छी नहीं हैं तत्काल उदाहरण: यदि आप ऑब्जेक्ट उपयोग के बाद मेमोरी को साफ़ करना भूल जाते हैं?)

इस मामले में, यह है बेहतर अगर आप स्मार्ट पॉइंटर्स का उपयोग करते हैं, लेकिन अब वास्तव में कहने के लिए बहुत कुछ है :) googling का आनंद लें!

HIH

0

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

Fruit GetFruit(std::string fruitName) { 
    if(fruitName != "apple" && fruitName != "banana") 
    { 
     fruitName = "kumquat"; 
    } 
    return Fruit(fruitName); 
} 

हालांकि इस कोड को वस्तु ही (अपने आंतरिक डेटा के सभी सहित) के साथ-साथ अगर बदले में कॉपी किया जा रहा है, में परिणाम होगा इसके आगे में भर में इसकी नक़ल उपयोग।

अधिक जावा-एस्क्यू होने के लिए आप इसके बजाय boost::shared_ptr का उपयोग करेंगे। फिर आप जावा में जैसे संदर्भित ऑब्जेक्ट से निपट रहे हैं:

boost::shared_ptr<Fruit> GetFruit(std::string fruitName) { 
    if(fruitName != "apple" && fruitName != "banana") 
    { 
     fruitName = "kumquat"; 
    } 
    return new Fruit(fruitName); 
} 
संबंधित मुद्दे