कक्षा के अंदर या बाहर समारोह की घोषणा


91

मैं एक जावा डेवलपर हूं, जो C ++ सीखने की कोशिश कर रहा है, लेकिन मुझे वास्तव में नहीं पता है कि मानक फ़ंक्शन घोषणाओं के लिए सबसे अच्छा अभ्यास क्या है।

कक्षा मैं:

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

या बाहर:

class Clazz
{
public:
    void Fun1();
}

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

मुझे लग रहा है कि दूसरा कम पढ़ा जा सकता है ...


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

यह प्रश्न आपको समझने में मदद कर सकता है।
ब्योर्न पोलेक्स

3
बस एक नोट: घोषणा हमेशा वर्ग के अंदर होती है, लेकिन परिभाषा या तो अंदर या बाहर होती है। प्रश्न शीर्षक और निकाय को एस / घोषणा / परिभाषा के अधीन किया जाना चाहिए / मुझे विश्वास नहीं करना चाहिए? stackoverflow.com/q/1410563/1143274
एवगेनी सर्गेव

1
कक्षा के अंदर कार्य की परिभाषा से बचना चाहिए। उन्हें स्पष्ट रूप से समझा जाता है inline
जॉन स्ट्रोड

@ जॉनस्ट्रोइड तो? inlineकेवल एक परिभाषा नियम को Clazz
शिथिल

जवाबों:


57

C ++ ऑब्जेक्ट ओरिएंटेड है, इस अर्थ में कि यह सॉफ्टवेयर डेवलपमेंट के लिए ऑब्जेक्ट ओरिएंटेड प्रतिमान का समर्थन करता है।

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

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

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

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

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

बस एक अच्छी किताब या दो चुनें और उन्हें कवर करने के लिए पढ़ें।


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

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

धन्यवाद, मुझे लगता है कि यह अब बहुत अच्छा पढ़ता है। माफ करना अगर मैं बुरा लगता हूँ। मैं अगली बार और अधिक सकारात्मक बनने की कोशिश करूंगा।
डैनियल एस।

15
प्रश्न का उत्तर नहीं देता है
पेट्र पेलर

1
@PetrPeller: तीसरे पैराग्राफ का क्या हिस्सा है जो आपके लिए स्पष्ट नहीं है?
6502

27

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

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

दोनों शब्दार्थ रूप से भिन्न हैं और यह केवल शैली की बात नहीं है।


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

18

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

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

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


10

"इनसाइड द क्लास" (I) पद्धति "क्लास के बाहर" (O) विधि के समान है।

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

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

सही उपयोग के लिए उदाहरण:

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.

File4: "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. 

आपका मतलब Clazz MyClazzऔर है Clazz MyClazz2?
चूपो_क्रो

4

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

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();  

(from: http://www.tutorialspoint.com/cplusplus/cpp_class_member_functions.htm ), दोनों तरीके कानूनी हैं।

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

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


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

2

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


1

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

क्लास का एक कंस्ट्रक्टर वर्चुअल फ़ंक्शंस के लिए जाँच करता है और एक वर्चुअल पॉइंटर को उचित वीटीएबल या वर्चुअल मेथड टेबल पर इंगित करता है , बेस क्लास कंस्ट्रक्टर को कॉल करता है, और करंट क्लास के वैरिएबल को इनिशियलाइज़ करता है, इसलिए यह वास्तव में कुछ काम करता है।

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


"इनलाइन" का व्यावहारिक रूप से इनलाइनिंग से कोई लेना-देना नहीं है। तथ्य यह है कि इन-लाइन में परिभाषित सदस्य फ़ंक्शन स्पष्ट रूप से इनलाइन हैं, ओडीआर उल्लंघन से बचने के लिए है।
बिग टेम्प

0

इनलाइन फ़ंक्शंस (फ़ंक्शंस जब आप उन्हें कक्षा में घोषित करते हैं) हर बार जब वे कॉल करते हैं तो उन्हें आपके मुख्य मेमरी कोड में चिपकाया जाता है। जब आप क्लास के बाहर फ़ंक्शन की घोषणा करते हैं, जब आप फ़्यूज़न को कॉल करते हैं तो यह उसी मेमोरी से आता है। यही कारण है कि यह बहुत बेहतर है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.