2012-01-31 30 views
60

बाहर घोषणा मैं एक जावा डेवलपर हैं जो सी ++ जानने की कोशिश कर रहा है, लेकिन मैं वास्तव में नहीं पता है कि सबसे अच्छा अभ्यास मानक समारोह घोषणाओं के लिए है।समारोह के अंदर या वर्ग

वर्ग में:

class Clazz 
{ 
public: 
    void Fun1() 
    { 
     //do something 
    } 
} 

या बाहर:

class Clazz 
{ 
public: 
    void Fun1(); 
} 

Clazz::Fun1(){ 
    // Do something 
} 

मुझे लगता है कि दूसरा एक कम पठनीय हो सकता है ...

+5

शायद सी ++ पर एक शुरुआती पुस्तक क्रम में हो सकती है? –

+28

@ डाउनवॉटर क्यों? मेरे प्रश्न में क्या गलत है? – JohnJohnGa

+0

वास्तव में यहां 3 विकल्प हैं। आपके दूसरे उदाहरण में हेडर फ़ाइल में फ़ंक्शन परिभाषा हो सकती है (लेकिन अभी भी रेखांकित नहीं है), या एक अलग '.cpp' फ़ाइल में। –

उत्तर

13

पहली बार अपने सदस्य समारोह को परिभाषित करता है inline function के रूप में, जबकि दूसरा नहीं है। इस मामले में फ़ंक्शन की परिभाषा शीर्षलेख में ही रहती है।

दूसरा कार्यान्वयन सीपीपी फ़ाइल में फ़ंक्शन की परिभाषा को रखेगा।

दोनों अर्थात् अलग हैं और यह शैली की बात नहीं है।

+1

http://www.cplusplus.com/doc/tutorial/classes/ एक ही जवाब देता है: "कक्षा वर्ग के कार्य को पूरी तरह से कक्षा में परिभाषित करने के बीच या केवल प्रोटोटाइप और बाद में इसकी परिभाषा को शामिल करने के बीच एकमात्र अंतर यह है कि पहला मामला फ़ंक्शन को स्वचालित रूप से कंपाइलर द्वारा इनलाइन सदस्य फ़ंक्शन माना जाएगा, जबकि दूसरे में यह एक सामान्य (इन-इनलाइन) क्लास सदस्य फ़ंक्शन होगा, जो वास्तव में व्यवहार में कोई अंतर नहीं रखता है। " – Buttons840

2

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

37

सी ++ भावना है कि यह सॉफ्टवेयर विकास के लिए वस्तु उन्मुख प्रतिमान का समर्थन करता है में वस्तु उन्मुख है।

हालांकि, अलग ढंग से जावा से, सी ++ समूह समारोह परिभाषाओं को कक्षाओं में मजबूर नहीं करता है: एक समारोह की घोषणा के लिए मानक सी ++ रास्ता सिर्फ एक समारोह की घोषणा करने के किसी भी वर्ग के बिना है।

आप विधि घोषणा/परिभाषा के बारे में बात कर रहे हैं तो बेहतर होगा आप तो मानक तरीका एक शामिल फ़ाइल (सामान्य रूप से .h या .hpp नाम) में सिर्फ घोषणा और एक अलग कार्यान्वयन फ़ाइल (सामान्य रूप से .cpp या .cxx नाम) में परिभाषा डाल करने के लिए है । मैं मानता हूं कि यह वास्तव में कुछ हद तक परेशान है और कुछ नकल की आवश्यकता है लेकिन इस तरह भाषा को डिजाइन किया गया था।

त्वरित प्रयोग और एकल फाइल के लिए परियोजनाओं के लिए कुछ भी काम करेगा ... लेकिन बड़ा परियोजनाओं के लिए इस अलगाव कुछ है कि व्यावहारिक रूप से आवश्यक है।

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

सी ++ जानने के लिए केवल उचित तरीका पढ़ रहे हैं ... कोई बात नहीं आप कैसे स्मार्ट हैं कोई रास्ता नहीं आप अनुमान लगा सकते हैं कि क्या समिति का फैसला किया है कर रहा है। (क्योंकि सही जवाब विसंगत है और ऐतिहासिक विरासत का एक परिणाम वास्तव में स्मार्ट जा रहा है कभी कभी भी एक समस्या है।)

बस एक good book या दो लेने और उन्हें कवर करने के लिए कवर पढ़ें।

+4

अगर कोई जावा से आता है और सी ++ पर मदद मांगता है, तो आप उसे क्या कहते हैं यदि आप कहते हैं कि "जिस भाषा को आप जानते हैं वह किसी चीज़ से भ्रमित है"? उसके पास अन्य भाषाओं की तुलना नहीं है, इसलिए यह उसे बहुत कुछ नहीं बताता है। जुनूनी भावनात्मक रूप से समझाए गए शब्द का उपयोग करने से बेहतर, जो ओपी को ज्यादा नहीं बताता है, आप शायद इस भाग को छोड़ने पर विचार कर सकते हैं। इसके अलावा, "हर चीज के लिए कक्षा का उपयोग" का संदर्भ क्या है? जावा में, आप किसी विधि के लिए कक्षा का उपयोग नहीं करते हैं। आप एक चर के लिए कक्षा का उपयोग नहीं करते हैं। आप फ़ाइल के लिए कक्षा का उपयोग नहीं करते हैं .. तो यहां "सबकुछ" क्या है? Ranting? –

+1

@DanielS: उस भाग को हटा दिया क्योंकि आपको स्पष्ट रूप से नाराज है (कोई विचार क्यों नहीं)। निश्चित रूप से मैं जावा के बारे में चिंतित नहीं हूं क्योंकि मैं वास्तव में जावा का उपयोग नहीं करता हूं, मैंने बस उस समय सोचा था कि ऑब्जेक्ट ऑब्जेस्ड प्रोग्रामिंग के रूप में ओओपी एक मजेदार मजाक था, जबकि स्पष्ट रूप से यह नहीं है। मैं जावा 1.1 प्रमाणित प्रोग्रामर रहा हूं लेकिन फिर फैसला किया कि, किसी कारण से मजबूर होने तक, मैं उस "प्रोग्रामिंग भाषा" का उपयोग नहीं करूंगा और अब तक मैं इसे टालने में सफल रहा हूं। – 6502

+0

धन्यवाद, मुझे लगता है कि यह अब बहुत बेहतर पढ़ता है। क्षमा करें अगर मुझे नाराज लगता है। मैं अगली बार अधिक सकारात्मक होने की कोशिश करूंगा। –

12

समारोह परिभाषा कक्षा के बाहर बेहतर है। यदि आवश्यक हो तो आपका कोड सुरक्षित रह सकता है। हेडर फ़ाइल केवल घोषणाएं देनी चाहिए।

मान लीजिए कि कोई आपके कोड का उपयोग करना चाहता है, तो आप उसे अपनी कक्षा के .h फ़ाइल और .obj फ़ाइल (संकलन के बाद प्राप्त) दे सकते हैं। उसे आपके कोड का उपयोग करने के लिए .cpp फ़ाइल की आवश्यकता नहीं है।

उस स्थिति में आपके कार्यान्वयन किसी और को दिखाई नहीं देता है।

8

"वर्ग के अंदर" (आई) विधि "कक्षा के बाहर" (ओ) विधि के रूप में ही है।

हालांकि, (i) का उपयोग तब किया जा सकता है जब कक्षा केवल एक फ़ाइल में उपयोग की जाती है (एक .cpp फ़ाइल के अंदर)। (ओ) का उपयोग हेडर फ़ाइल में होने पर किया जाता है। सीपीपी फाइलें हमेशा संकलित होती हैं। हेडर फाइल संकलित किए जाते हैं जब आप #include "header.h" का उपयोग करें।

यदि आप हेडर फ़ाइल में (i) का उपयोग करते हैं, तो फ़ंक्शन (Fun1) प्रत्येक बार जब आप "header.h शामिल" शामिल करेंगे, घोषित किया जाएगा। यह एक ही समारोह को कई बार घोषित कर सकता है। संकलन करना मुश्किल है, और त्रुटियों का भी कारण बन सकता है। सही उपयोग के लिए

उदाहरण:

File1: "Clazz.h"

//This file sets up the class with a prototype body. 

class Clazz 
{ 
public: 
    void Fun1();//This is a Fun1 Prototype. 
}; 

File2: "Clazz.cpp"

#include "Clazz.h" 
//this file gives Fun1() (prototyped in the header) a body once. 

void Clazz::Fun1() 
{ 
    //Do stuff... 
} 

file3: "UseClazz.cpp"

#include "Clazz.h" 
//This file uses Fun1() but does not care where Fun1 was given a body. 

class MyClazz; 
MyClazz.Fun1();//This does Fun1, as prototyped in the header. 

फ़ाइल 4: "AlsoUseClazz.cpp"

#include "Clazz.h" 
//This file uses Fun1() but does not care where Fun1 was given a body. 

class MyClazz2; 
MyClazz2.Fun1();//This does Fun1, as prototyped in the header. 

File5: "DoNotUseClazzHeader.cpp"

//here we do not include Clazz.h. So this is another scope. 
class Clazz 
{ 
public: 
    void Fun1() 
    { 
     //Do something else... 
    } 
}; 

class MyClazz; //this is a totally different thing. 
MyClazz.Fun1(); //this does something else. 
3

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

class Box 
{ 
    public: 

    double length; 
    double breadth;  
    double height;  

    double getVolume(void) 
    { 
     return length * breadth * height; 
    } 
}; 

क्या आप गुंजाइश संकल्प ऑपरेटर का उपयोग, केवल महत्वपूर्ण वर्ग के बाहर एक ही समारोह को परिभाषित कर सकते :: के रूप में यहाँ

double Box::getVolume(void) 
{ 
    return length * breadth * height; 
} 

इस प्रकार है, पसंद करते हैं मुद्दा यह है कि आपको :: ऑपरेटर से पहले कक्षा का नाम उपयोग करना होगा।

Box myBox;   

myBox.getVolume(); 

(से: http://www.tutorialspoint.com/cplusplus/cpp_class_member_functions.htm) , दोनों तरीकों से कानूनी रहे हैं एक सदस्य समारोह एक वस्तु इस प्रकार के रूप में ही है, जहां यह है कि वस्तु से संबंधित डेटा में हेरफेर होगा पर बिंदी ऑपरेटर का उपयोग बुलाया जाएगा (।)।

मैं एक विशेषज्ञ नहीं हूं, लेकिन मुझे लगता है, अगर आप एक फ़ाइल में केवल एक वर्ग परिभाषा डालते हैं, तो इससे कोई फर्क नहीं पड़ता।

लेकिन यदि आप आंतरिक कक्षा की तरह कुछ लागू करते हैं, या आपके पास एकाधिक श्रेणी परिभाषा है, तो दूसरा को पढ़ना और बनाए रखना मुश्किल होगा।

+0

क्या आप उस लिंक से प्रासंगिक सामग्री को अपनी पोस्ट के बॉडी में ला सकते हैं, और इस प्रकार मृत लिंक के खिलाफ भावी-सबूतिंग कर सकते हैं? धन्यवाद – JustinJDavies

1

एक वर्ग के अंदर परिभाषित एक फ़ंक्शन डिफ़ॉल्ट रूप से एक इनलाइन फ़ंक्शन के रूप में माना जाता है। एक सरल कारण है कि आप बाहर अपने कार्य परिभाषित करना चाहिए:

आभासी कार्यों के लिए वर्ग चेकों के एक निर्माता और उचित vtable या virtual method table को इंगित करने के लिए एक आभासी सूचक initializes, आधार वर्ग निर्माता कहता है, और के चर initializes वर्तमान वर्ग, तो यह वास्तव में कुछ काम करता है।

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

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