2010-11-28 20 views
5

मुझे यकीन नहीं है कि सी ++ में मेरे कार्यों को कैसे ऑर्डर करें। सी में, मैंने बस एक फ़ंक्शन रखा है जो उस फ़ंक्शन के नीचे एक और फ़ंक्शन का उपयोग करता है, जितना संभव हो सके - यह बहुत आम है। इस तरह:सी ++ में फ़ंक्शंस कैसे ऑर्डर करें?

void bar() 
{ 
} 

void foo() 
{ 
    bar(); 
} 

हालांकि, सी ++ में, वहाँ कार्यों के कई प्रकार हैं:

  • नि: शुल्क कार्यों
  • निजी सदस्य कार्यों
  • लोक सदस्य कार्यों
  • स्टेटिक सदस्य कार्यों

मैं वर्तमान में maki हूँ निर्भर जैसे कि वे किस तरह .hpp फ़ाइल में आदेश दिया जाता है पर एनजी मेरी समारोह आदेश: निर्माता foo का उपयोग करता है() या बार

class Foo_bar { 
public: 
    Foo_bar(); 
    void foo(); 
private: 
    int some_member; 
    void bar(); 

लेकिन अब(), इन में निर्माता नीचे हो जाएगा स्रोत फ़ाइल, मेरे सामान्य आदेश के साथ असंगत। मैं निश्चित रूप से मेरी शीर्ष लेख को पुन: व्यवस्थित कि खातों को भी लेने के लिए कर सकते हैं:

class Foo_bar { 
private: 
    int some_member; 
    void bar(); 

public: 
    void foo(); 
    Foo_bar(); 

लेकिन मुझे लगता है कि एक गड़बड़ है।

इसके अलावा, जावा में, मेरा पहला उदाहरण के विपरीत आम हो रहा है:

void foo() 
{ 
    bar(); 
} 

void bar() 
{ 
} 

को ऊपर से नीचे OOP में आम सोच, इसके विपरीत में की वजह से शायद इसलिए है कि नीचे से ऊपर में आम सोच प्रक्रियात्मक/कार्यात्मक प्रोग्रामिंग। हालांकि, मुक्त कार्यों के साथ जिनके प्रोटोटाइप नहीं हैं, यह टॉप-डाउन शैली संभव नहीं है।

क्या सी ++ में लगातार क्रम में कार्यों को ऑर्डर करना भी संभव है?

+0

मैं मैं क्या कर रहा हूँ पर काम कर रहा द्वारा अपने कार्यों ऑर्डर करने के लिए पसंद करते हैं घोषणाओं की सूची और समान रूप से परिभाषाओं की सूची ... आदेश - इतनी है कि जब एक फ़ाइल खोलना, यह संभावना है कि मैं जो देखना चाहता हूं वह शीर्ष पर है। उस ने कहा, मेरे पास ":: methodName" की तलाश में बहुत सारी अभ्यास है - इसलिए शायद मेरी विधि सबसे अच्छी नहीं है;) – sje397

+0

मुझे प्रश्न समझ में नहीं आता है। सभी कार्यों में प्रोटोटाइप होते हैं और यदि आपको आवश्यकता हो तो आप हेडर फ़ाइल या कहीं और में मुफ्त फ़ंक्शंस घोषित कर सकते हैं। जब तक आपके द्वारा उपयोग किए जाने वाले किसी भी फ़ंक्शन के लिए घोषणाएं दिखाई देती हैं, तो आप किसी भी क्रम में फ़ंक्शन परिभाषाओं को ऑर्डर कर सकते हैं। आपके कार्यों को किसी भी तरह से व्यवस्थित करने से आपको क्या रोक रहा है जो आपको लगता है? –

+0

@ चार्ल्स: नीचे फोर्नी की टिप्पणियां देखें। जाहिर है, वह भाषा सुविधाओं का उपयोग करने के बारे में सोचता है कि उनके लिए क्या बुरा था ...? ऐसा लगता है कि वह मूल रूप से अत्यधिक व्यक्तिपरक प्रश्न पूछ रहा है "मैं मेरे लिए उपलब्ध भाषा सुविधाओं का उपयोग नहीं करना चाहता, आप इसके बजाय क्या सुझाव देते हैं?" यह कहने जैसा है "मुझे वास्तव में घुंघराले ब्रेसिज़ पसंद नहीं है, इसलिए मैं उनसे बचने के लिए प्रति ब्लॉक 1 कथन फिट करने की कोशिश करता हूं, क्या ऐसा करने का एक निरंतर तरीका है इसलिए मुझे घुंघराले ब्रेसिज़ का उपयोग कभी नहीं करना पड़ेगा?" और किसी को यह कहने की उम्मीद है "हाँ! अगर (एक्सपी) कथन; अगर (एडीएक्सपी) कथन 2; आपको 2 आंकड़े बिना ब्रेसिज़ के मिलते हैं!" क्यू – Loduwijk

उत्तर

6

यह संभव है। आपको forward declaration का उपयोग करना होगा।

इसे परिभाषित करने से पहले एक फ़ंक्शन घोषित करें, और अन्य फ़ंक्शंस इसे बिना किसी समस्या के देख पाएंगे, भले ही उन्हें पहले परिभाषित किया गया हो।

तो, आप C++ यह करने के लिए सक्षम होना चाहिए:

void bar(); // forward declaration; note that function bar isn't defined yet 

void foo() 
{ 
    bar(); // foo knows that bar is declared, so it will search for bar's definition 
} 

void bar() // here bar is defined, so foo will use this when needed 
{ 
} 
+0

यह तकनीकी रूप से संभव है, हां, लेकिन आईएमओ हर मुफ्त समारोह की घोषणा करने के लिए काफी बदसूरत है। मैं अपने कोड के भीतर पूरी तरह से हेडर में इस्तेमाल किए गए मुफ्त कार्यों के प्रोटोटाइप नहीं डाल रहा हूं, मैं उस पर स्कॉट मेयर्स पर भरोसा कर रहा हूं। http://www.drdobbs.com/184401197 – forneo

+2

@ फोर्नियो: यदि आपका मतलब है कि आप इसे हेडर फ़ाइल में नहीं डाल रहे हैं, तो यह ठीक है, डारी ने यह नहीं कहा था कि आपको चाहिए। आप इसे उसी फ़ाइल के शीर्ष पर प्रोटोटाइप के साथ घोषित कर सकते हैं जिसका आप उपयोग कर रहे हैं। यदि शीर्षलेख से आपका मतलब है कि उसी फ़ाइल के शीर्षक (शीर्ष) पर, क्यों नहीं? मैं अपनी फाइलों के शीर्ष पर लगभग हर चीज का प्रोटोटाइप करता हूं, भले ही उन्हें होने की आवश्यकता न हो, और यह ठीक है; यह भयानक नहीं है, शीर्ष पर कार्यों की एक सूची देखने में सक्षम होना अच्छा है। यदि आप कह रहे हैं कि आप ऐसा नहीं करेंगे, तो यह आपका नुकसान है, आप कह रहे हैं "मैं भाषा सुविधाओं का उपयोग नहीं करना चाहता हूं" और आपके पास कोई प्रश्न नहीं है। – Loduwijk

+0

मुझे लगता है कि मैंने गलत समझा, मैंने भी उसी फ़ाइल में आगे नहीं डालने पर विचार किया। इससे मुझे टॉप-डाउन ऑर्डरिंग करने की अनुमति मिल जाएगी। – forneo

1

आप सही एक हेडर फाइल में वर्ग की घोषणा? और इसे एक अलग फ़ाइल में लागू करें? यदि आप केवल कार्यान्वयन फ़ाइल में कन्स्ट्रक्टर को कार्यान्वित करते हैं और शीर्षलेख में नहीं, तो मुझे नहीं लगता कि आपको उस समस्या का अनुभव होगा जो आपने उल्लेख किया है (क्योंकि पूरे हेडर को foo() या bar() पर कॉल करने के लिए देखा जाता है।

+0

हां, कोई तकनीकी समस्या नहीं है, मैं बस यह कह रहा हूं कि यह मेरे सामान्य तल-अप आदेश के साथ असंगत है। – forneo

1

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

कक्षा में, चीजें आमतौर पर अलग होती हैं, क्योंकि लगभग कोई मामला नहीं है क्या आप अपनी कक्षा को शीर्षलेख में पूरी तरह कार्यान्वित करते हैं, इस प्रकार जब आप स्रोत फ़ाइल में फ़ंक्शंस को परिभाषित कर रहे होते हैं तो घोषणा हमेशा पढ़ी जाती है।

मैं आमतौर पर "फ़ंक्शन" और समूह जैसे कार्यों में ऑर्डर देता हूं। गेटर्स और सेटर्स, कन्स्ट्रक्टर/विनाशक (यदि संभव हो)।

+0

डारी के जवाब का मेरा जवाब देखें, मुझे नहीं लगता कि हर समारोह को हेडर में घोषित किया जाना है, स्कॉट मेयर्स कुछ अच्छे अंक बनाते हैं। – forneo

+0

सहमत हैं, स्रोत फ़ाइल के लिए विशिष्ट प्रत्येक आंतरिक फ़ंक्शन शीर्षलेख में होने की आवश्यकता नहीं है, अगर आप इसे वहां नहीं चाहते हैं। लेकिन फिर आप * स्रोत फ़ाइल में फ़ंक्शंस घोषित कर सकते हैं, और इन घोषणाओं के नीचे उन्हें किसी भी तरह फिट करने के लिए आदेश दे सकते हैं। – rubenvb

+0

सहमत - हालांकि टेम्पलेट्स के साथ भी, मैं वास्तविक टेम्पलेटेड सामान को अंतर्निहित गैर-टेम्पलेट कोड के साथ छोटा बनाना चाहता हूं। यह थोड़ा और काम है, लेकिन यह ब्लोट से बच सकता है, और हेडर को अपेक्षाकृत पठनीय रखने में मदद करता है। हालांकि ब्लोट मुद्दे पर, यह संभव है कि टेम्पलेट्स एक बार वैसे भी कम ब्लोट-प्रवण हों। – Steve314

0

व्यक्तिगत रूप से, मुझे उन चीज़ों को देखना पसंद है जिन्हें फ़ाइल के शीर्ष के पास कहीं और (जिन्हें लोगों को अक्सर ढूंढना/पढ़ना होगा) से संदर्भित किया जाएगा। आंतरिक, जो एक बार स्थिर हो, उम्मीद है कि बाद में भुला दिया जा सकता है।

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

लेकिन मूल रूप से, चीजों को समान या तार्किक रूप से संबंधित चीजों को एक साथ रखना है। एक प्रारंभ विधि एक अंतिम विधि के समीप होगी, एक चरण_To_Next विधि एक चरण_To_Prev विधि के समीप, आदि समूह समान उद्देश्यों, समान पैरामीटर, और आमतौर पर एक साथ उपयोग किया जा रहा है सभी अच्छे हैं।

क्या कॉल करता है जो अधिकतर एक कार्यान्वयन विवरण है, इसलिए कुछ ऐसा नहीं है जो आपको अपनी लाइब्रेरी के उपयोगकर्ता को पढ़ाए जाने वाले हेडर फाइलों में जरूरी है - हालांकि कार्यान्वयन कोड में चीजें अलग-अलग हो सकती हैं। जैसा कि अन्य ने बताया है, आगे की घोषणाएं इसके साथ कुछ स्वतंत्रता की अनुमति देती हैं।

सबसे महत्वपूर्ण (1) एक सतत शैली को अपनाने, और (2) संदिग्ध मामलों के बारे में ज्यादा चिंता न करें।

+0

इस टिप्पणी पर कि क्या आप एक रेखांकित सदस्य विधि से अभी तक घोषित सदस्य विशेषता का उपयोग नहीं कर सकते हैं या नहीं, जवाब यह है कि आप कर सकते हैं, यह कानूनी और सामान्य है।'संरचना परीक्षण {शून्य foo() {std :: cout << x << std :: endl; } int एक्स; }; 'सही कोड है। –

1

कक्षा परिभाषा में कार्यों को पुन: व्यवस्थित करने के बारे में आपकी चिंता सी ++ 03 मानक से निम्नलिखित दो उद्धरणों द्वारा स्पष्ट के रूप में सही नहीं है।

$ 9,2/2- "एक वर्ग वर्ग विनिर्देशक। के समापन} वर्ग सदस्य-विनिर्देश के भीतर एक पूरी तरह से परिभाषित ऑब्जेक्ट प्रकार (3.9) (या पूरा प्रकार) माना जाता है , वर्ग निकायों, डिफ़ॉल्ट तर्कों और निर्माता ctor-initializers (नेस्टेड कक्षाओं में ऐसी बातें भी शामिल हैं) समारोह के भीतर पूरा माना जाता है। अन्यथा यह अपने ही वर्ग सदस्य-विनिर्देश भीतर अधूरा माना जाता है। "

और

$ 3.4.1/8 - "एक सदस्य समारोह (9.3) के परिभाषा में इस्तेमाल एक नाम दसवीं कक्षा समारोह के declaratorid29 निम्न में से ) एक में घोषित किया जाएगा - ब्लॉक जो में यह प्रयोग किया जाता है या एक संलग्न ब्लॉक (6.3) में, या

में इसके उपयोग से पहले

: निम्न तरीकों से

- दसवीं कक्षा का सदस्य होना या X (10.2) का एक आधार वर्ग के एक सदस्य, या

किया जाएगा - अगर एक्स वर्ग वाई (9 की एक नेस्टेड वर्ग है।7), वाई के एक सदस्य होगा, या वाई का आधार वर्ग के एक सदस्य होंगे (यह देखने वाई के enclosing वर्गों के लिए बदले में लागू होता है,) अंतरतम संलग्नित क्लास के साथ शुरू, 30) या

- अगर एक्स एक स्थानीय वर्ग (9.8) है या एक स्थानीय वर्ग के एक नेस्टेड वर्ग, से पहले एक ब्लॉक में दसवीं कक्षा की परिभाषा दसवीं कक्षा की परिभाषा, या

संलग्न है - अगर एक्स है नेमस्पेस एन का सदस्य, या एक कक्षा का घोंसला वाला वर्ग है जो एन का सदस्य है, या एक लो है कैल क्लास या फ़ंक्शन के स्थानीय वर्ग के भीतर नेस्टेड क्लास, नेमस्पेस एन में या एन के संलग्न नामस्थानों में से एक में सदस्य फ़ंक्शन परिभाषा से पहले एन का सदस्य है।

सामान्य नियम के रूप में, सी ++ में, फ़ंक्शन परिभाषाओं को उनके उपयोग के बिंदु पर दिखाई देना होगा। उपरोक्त उद्धरणों द्वारा सचित्र के रूप में वर्ग सदस्य कार्यों का एकमात्र अपवाद है।

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

2

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

जो एक वर्ग के कोड पढ़ा जाएगा लोगों के 3 प्रकार के होते हैं:

  • जो लोग चाहते हैं इसे इस्तेमाल करता है करने के लिए (और उसके आंतरिक के बारे में ज्यादा परवाह नहीं है)
  • जो लोग चाहते हैं के वारिस के लिए अपनी कक्षा से (और उसके आंतरिक के बारे में ज्यादा परवाह नहीं है)
  • जो लोग वास्तव में अपने वर्ग पर हैक करना चाहते हैं, और इस तरह अपनी आंतरिक

इस कारण से की परवाह, मैं इतना हेडर ऑर्डर करने के लिए कोशिश कि हम कोई भी एर बंद कर सकता है एक बार वह मिल गया कि वह क्या के लिए, जिसका अर्थ है देख रहा था:

class Foo 
{ 
public: 
    // types 
    // static methods 
    // methods (usually constructors, 
    //   then simple accessors, 
    //   then more complicated stuff) 

protected: 
    // same pattern 

private: 
    // same pattern 
    // attributes 
}; 

// Free functions about this class 

// Implementation of inline/template methods 

कभी कभी मैं पहले से कुछ प्रकार की घोषणा करने के भले ही वे निजी हैं की जरूरत है, लेकिन यह दुर्लभ है। इस आदेश का लक्ष्य एक पाठक को जो कुछ भी चाहिए वह प्राप्त करने से पहले उसे पढ़ने के लिए पूरी तरह से कम करना है (और पढ़ना बंद कर देता है और वह आपके कोड को देखने के लिए खुद को बाधित करने से पहले क्या कर रहा था) पर वापस जाता है।

फिर, "सहायक" के तरीकों के बारे में है, यह कोड के प्रकार पर निर्भर:

    टेम्पलेट कोड के लिए
  • , मैं एक "विवरण" नाम स्थान का उपयोग करें, यह दोनों पाठक है कि वह चिंतित नहीं होना चाहिए करने के लिए स्पष्ट है इसके बारे में और यह नाम अपने नामस्थान में अलग करते हैं ताकि वे नियमित कोड के लिए कोड पूर्ण करने के उपकरण
  • में पॉप-अप न करें, मैं स्रोत फ़ाइल के भीतर एक अज्ञात नेमस्पेस का उपयोग करता हूं, जो तब भी बेहतर होता है जब यह वास्तव में अदृश्य प्रतीक उत्पन्न करता है और मैं ODR का उल्लंघन करने का जोखिम नहीं चलाता।क्रम में घोषणाओं की एक सूची प्रदान करने के लिए

    include/ 
        foo.hpp 
    
    src/ 
        fooImpl.hpp --> #include "foo.hpp" 
        foo.cpp  --> #include "fooImpl.hpp" 
    

    :

कुछ कोड सहायकों का एक बहुत की आवश्यकता हो सकती है, मैं स्रोत निर्देशिका में एक समर्पित हैडर फ़ाइल बनाने के लिए, निम्नलिखित संरचना दे जाते हैं पाठक, क्योंकि परिभाषाओं की सूची से घोषणाओं को निकालने के बजाय घोषणाओं की सूची ब्राउज़ करना आसान है, जो भी इंडेंटेशन और शैली है।

और बेशक, हमेशा यह आसान बनाने के लिए, मैं हमेशा

+0

ऐसे लोग भी हैं जो आपके कोड से सीखना चाहते हैं। –

+0

@druciferre: जब मैं उस बिंदु तक पहुंच जाता हूं जहां लोग मेरे कोड से सीखना चाहते हैं, तो मैं बहुत खुश रहूंगा: डी –

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