2012-02-19 13 views
8

मैं सी ++ सीख रहा हूं, और मुझे ऑब्जेक्ट उन्मुख अध्याय मिला है। बयान के अंदर वस्तुओं को बनाने के बारे में मेरे पास एक सवाल है।सशर्त सी ++ कथन में ऑब्जेक्ट बनाएं

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

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

तो मेरा सवाल यह है कि इन वस्तुओं को कैसे बनाया जाए? मैं समझता हूं कि बिना किसी तर्क के किसी ऑब्जेक्ट को कैसे बनाया जाए (यानी newobj की रिपोर्ट करें;), और तर्क के साथ (यानी newobj (स्ट्रिंग स्ट्रिंग) की रिपोर्ट करें;)। असल में, मुझे लगता है कि शुरुआत में मेरे मुख्य कार्य के शीर्ष पर इन वस्तुओं को कैसे बनाया जाए। लेकिन उपयोगकर्ता विकल्पों के आधार पर बयान के अंदर उन्हें बनाना संभव है? यहाँ मैं अब तक स्पष्ट रूप से है और, है, यह काम नहीं करता:

#include <iostream> 
#include <string> 
#include "report.h" 
using namespace std; 

bool enter_company_name();   // return true if user wants to enter company name 
bool print_form();    // return true if user wants to print in formatted output 

int main() 
{ 
    string company_name, 
    report_name; 
    bool name = false, 
    format = false; 

    name = enter_company_name(); 
    format = print_form(); 

    if (name) 
    { 
     cout << "Enter company name: "; 
     getline(cin, company_name); 
     cout << "Enter report name: "; 
     getline(cin, report_name); 
     Report header(company_name, report_name); // THIS IS MY PROBLEM 
    } 
    else 
     Report header; // THIS IS MY PROBLEM 

    if (format) 
    header.print_formatted(); 
    else 
    header.print_one_line(); 

    return 0; 
} 

bool enter_company_name() 
{ 
    char choice; 

    cout << "Do you want to enter a name?\n>"; 
    cin >> choice; 

    if (choice == 'y' || choice == 'Y') 
    return true; 
    else 
    return false; 
} 

bool print_form() 
{ 
    char choice; 

    cout << "Do you want to print a formatted header?\n>"; 
    cin >> choice; 

    if (choice == 'y' || choice == 'Y') 
    return true; 
    else 
    return false; 
} 

तो मैं डिफ़ॉल्ट मान का उपयोग कर एक वस्तु बनाने यदि कुछ भी निर्दिष्ट कर रहे हैं, या उपयोगकर्ता मूल्यों के साथ एक बनाना चाहते हैं कि अगर पसंद है दिया हुआ। मैं बस यह नहीं समझ सकता कि इसे सी ++ में इंटरैक्टिव तरीके से कैसे किया जाए। मैं अब तक कहीं भी इसी तरह के कोई प्रश्न नहीं ढूंढ पाया है।

मैं जो नज़दीकी चीज में आया हूं, वह कुछ करने के लिए पॉइंटर्स का उपयोग करता है जो मैं करना चाहता हूं, लेकिन जिस पुस्तक का मैं उपयोग कर रहा हूं वह अभी तक पॉइंटर्स तक नहीं मिला है, और मैं एक तरीका जानने का प्रयास करना चाहता हूं ऐसा करें जो अध्याय की सीमाओं के भीतर रहता है जिसमें मैं काम कर रहा हूं (यानी पॉइंटर्स का उपयोग नहीं कर रहा हूं)।

मैंने हेडर फ़ाइल या कक्षा कार्यान्वयन फ़ाइल शामिल नहीं की क्योंकि मुझे नहीं लगता कि वे यहां प्रासंगिक हैं।

अग्रिम धन्यवाद!

+0

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

+0

आप स्कोपिंग मुद्दों में भाग रहे हैं - यहां एक समान प्रश्न है, जहां कोई सूचक का उपयोग करने का उत्तर देता है: http://stackoverflow.com/questions/1793807/declaring-a-variable-in-an-if-else-block-in -सी - आपके लिए, आप 'if' कथन के बाहर 'रिपोर्ट' ऑब्जेक्ट बना सकते हैं, जो ऑब्जेक्ट के लिए डिफ़ॉल्ट कन्स्ट्रक्टर का आह्वान करेगा, और यदि आपको 'नाम' मिलता है, तो आप इसे किसी अन्य रिपोर्ट पर पुनः सौंप सकते हैं '। बेशक, यदि आपके पास डिफॉल्ट कन्स्ट्रक्टर नहीं है, तो यह समाधान काम नहीं करेगा और संकलक आपको चिल्लाएगा। – birryree

+0

@orangeoctopus: यह ** ** संभव है और वास्तव में काफी तुच्छ है। –

उत्तर

7

मुझे नहीं पता कि मैं आपका प्रश्न सही तरीके से समझ गया हूं, लेकिन क्या आप सिर्फ/अन्य ब्लॉक से पहले रिपोर्ट घोषित नहीं कर सकते हैं और फिर इसके अंदर प्रारंभ कर सकते हैं?

Report header; 

if (...) { 
    header = Report(); 
else 
    header = Report(name,company); 

या एक छोटे रास्ते में:

Report header; // calls default constructor 

if (shouldInitializeWithParams) { 
    header = Report(name,company); 
} 

बेशक इस खाली निर्माता परिभाषित किया गया है की आवश्यकता है।

+1

'हेडर = रिपोर्ट();' लाइन को हेडर रिपोर्ट 'के रूप में भी नहीं चाहिए,' डिफ़ॉल्ट कन्स्ट्रक्टर का आह्वान करेगा। – birryree

+0

हां, यह स्पष्टता के लिए था। असल में पुनर्नवीनीकरण की आवश्यकता नहीं है, क्योंकि यह पहले ही शुरू हो जाएगा। – Jack

+0

सच है, और वास्तव में वह ''''''''''''''''''''''''''''''''''''''' _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ – birryree

2

हम नहीं जानते कि कक्षा Report कॉपी-सक्षम है, पॉइंटर्स का उपयोग करने के लिए बेहतर है।

Report * header; 

if (...) { 
    header = new Report(); 
else 
    header = new Report(name,company); 

// after all don't forget 
delete header; 

और निश्चित रूप से आपको लगता है कि

header->print_formatted(); 
+0

बेहतर? अगर रिपोर्ट कॉपी करने योग्य है तो कम से कम * जांच * के लिए बेहतर नहीं होगा? –

+0

यदि आप कर सकते हैं, तो इसे जांचें। मैं नहीं कर सकता, माफ करना :) क्या यह निक हो सकता है - मुझे नहीं पता, कॉपी करने के साथ किसी भी समस्या से बचने के लिए, मेरे लिए पॉइंटर्स का उपयोग करना बेहतर जवाब है। –

+1

हम नहीं जानते कि कक्षा 'रिपोर्ट' एक अलग फ़ंक्शन का उपयोग करने के लिए कॉपी करने योग्य है या नहीं, जिसके लिए केवल' रिपोर्ट 'की आवश्यकता होती है। इसके अलावा यदि आप अभी भी पॉइंटर्स को कच्चे पॉइंटर्स के बजाय 'std :: unique_ptr' का उपयोग करने की सलाह देते हैं। – Begemoth

0

तरह header सूचक का उपयोग करना चाहिए मुझे यकीन है कि अगर मैं अपने प्रश्न ठीक से समझा नहीं हूँ। क्षमा करें अगर आप जवाब पढ़ते हैं और महसूस करते हैं कि यह मामला है।

लेकिन फिर भी, मुझे लगता है कि मुख्य रणनीति कन्स्ट्रक्टर ओवरलोडिंग का उपयोग करना होगा। यानी, आप दोनों के लिए रचनाकार परिभाषित करते हैं: जब कोई पैरामीटर पारित नहीं होता है और जब पैरामीटर पारित होते हैं तो मामला। पूर्व (जिसे आप डिफ़ॉल्ट कन्स्ट्रक्टर के रूप में संदर्भित करते हैं) कंपनी को प्रारंभ करेंगे और नामों को डिफ़ॉल्ट मानों पर रिपोर्ट करेंगे। उत्तरार्द्ध comapany और रिपोर्ट नामों के लिए प्राप्त मानकों को आवंटित करेगा।

पॉइंटर्स के उपयोग के लिए: आप 'रिपोर्ट' (वर्ग) के कई ऑब्जेक्ट्स 'घोषित' करके इसे टाल सकते हैं। उदाहरण के लिए, आप हेडर (ऑब्जेक्ट्स) की सरणी बना सकते हैं। और फिर जब आप उपयोगकर्ता प्रतिक्रिया देते हैं तो आप इसे 'परिभाषित' कर सकते हैं।

लेकिन पॉइंटर्स का उपयोग करके, आप रनटाइम (गतिशील असाइनमेंट) में सब कुछ कर रहे हैं जबकि सरणी (या कई ऑब्जेक्ट्स घोषित करने) का उपयोग करते समय: राशि तय की जाती है। यह अक्षम हो सकता है।

+0

गलत संदर्भ में उपयोग किए जाने पर गतिशील या स्थैतिक आवंटन दोनों अक्षम हो सकते हैं। –

2

दिमाग में आने वाली सबसे सरल चीज कोड प्रवाह पर थोड़ा रिफैक्टरिंग कर रही है। एक फ़ंक्शन बनाएं जो इनपुट को संसाधित करता है और निर्मित ऑब्जेक्ट देता है:

Report loadReport() { 
    if (user_input()) { 
     // read input 
     return Report(name,company); 
    } else { 
     return Report(); 
    } 
} 

फिर फ़ंक्शन को मुख्य से कॉल करें। डिजाइन में छोटा बदलाव एक ऐसे कार्य का परिचय है जिसकी एकल जिम्मेदारी उपयोगकर्ता इनपुट से Report बना रही है, जो वास्तव में एक फ़ंक्शन के रूप में समझ में आता है।

11

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

Report makeReport() { 
    if (enter_company_name()) { 
     ... 
     return Report(name, company); 
    } 
    return Report(); 
} 

... 
Report report = makeReport(); 

एक वैकल्पिक दृष्टिकोण conditonally Report एक ही रास्ता या अन्य बनाने के लिए त्रिगुट ऑपरेटर का उपयोग करने के लिए है:

bool get_company_name = enter_company_name(); 
std::string name(get_company_name? read_name(): ""); 
std::string company(get_company_name? read_company(): ""); 
Report report = get_company_name? Report(name, company): Report(); 

इन सभी दृष्टिकोणों का मानना ​​है कि Report कक्षा वास्तव में कॉपी करने योग्य है।

+0

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

+0

+ 1 डी आईएमएचओ स्वीकार्य उत्तर से बेहतर है, जिसके लिए एक डिफ़ॉल्ट 'ctor() 'की आवश्यकता होती है - ऐसा कुछ नहीं जो हम हमेशा सक्षम या प्रदान करने के इच्छुक हैं। मैं बस एक गैर-डिफ़ॉल्ट ctor में भाग गया, जिसे सशर्त रूप से तर्कों के 1 सेटों के साथ बुलाया जाना चाहिए, और इसे अपना रास्ता हल कर दिया। (फिर इसे अपने अस्थायी के सदस्य को वापस कर एक कदम आगे ले लिया ... हे) जैसा कि आपने कहा था, इसके लिए प्रतिलिपि की आवश्यकता है, लेकिन मेरे लिए, प्रतिलिपि ठीक है लेकिन एक डिफ़ॉल्ट 'ctor() 'नहीं है। –

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