2012-06-04 8 views
16

क्या कार्यान्वयन फ़ाइल में Graph:: पुनरावृत्ति से बचने का कोई तरीका है, फिर भी कक्षा को हेडर + कार्यान्वयन में विभाजित किया गया है? के रूप में इस तरह के में:क्या कार्यान्वयन फ़ाइल में कक्षा का नाम दोहराए जाने से बचाना संभव है?

हैडर फ़ाइल:

#ifndef Graph_H 
#define Graph_H 

class Graph { 
public: 
    Graph(int n); 
    void printGraph(); 
    void addEdge(); 
    void removeEdge(); 
}; 

#endif 

कार्यान्वयन फ़ाइल:

Graph::Graph(int n){} 
void Graph::printGraph(){} 
void Graph::addEdge(){} 
void Graph::removeEdge(){} 
+1

यह सही लगता है कि आप कार्यान्वयन में हेडर को शामिल नहीं करना चाहते हैं। – dasblinkenlight

+3

क्या आप पूछ रहे हैं कि क्या आप कार्यान्वयन में 'ग्राफ़ ::' टाइप करने से बच सकते हैं? – GManNickG

+2

मुझे पता है कि यह सही है, लेकिन मैं पूछ रहा हूं कि ग्राफ :: दोहराने के बिना कोई दूसरा तरीका है या नहीं .. .. –

उत्तर

7

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

9

आप printGraph के सामने "ग्राफ़ ::" टाइप से बचना चाहते हैं, addEdge आदि, तो जवाब दुर्भाग्य से "नहीं" है। सी #+ के समान "आंशिक वर्ग" सुविधा सी ++ में उपलब्ध नहीं है और किसी भी वर्ग (जैसे "ग्राफ") का नाम नामस्थान नहीं है, यह एक दायरा है।

+0

सीमा को देखने के दो प्रेरणादायक तरीकों के लिए +1। –

2

नहीं, इससे बचने का कोई तरीका नहीं है। अन्यथा, आप कैसे जानते होंगे कि किसी दिए गए फ़ंक्शन परिभाषा को क्लास फ़ंक्शन के लिए या स्थैतिक फ़ंक्शन के लिए है?

+0

आप निश्चित रूप से वर्तमान मानक के लिए सही हैं। मैं नाटक करना चाहता हूं कि आप कल्पित रूप से बोल रहे थे, हालांकि ;-) तो मेरी टिप्पणियों के अनुसार ओपी: सदस्यों को परिभाषित करने के लिए प्रस्तावित 'नेमस्पेस क्लास' का उपयोग करके आप बहुत आसानी से असंबद्ध हो जाएंगे: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0223r0.html - और वाह, क्या मुझे आशा है कि यह गोद लिया जाएगा ... और मुझे बहुत दुख हुआ है कि ऐसा लगता है कि सी ++ 17 :(अगर कोई इस छोटे से न्यायाधीश का न्याय करता है एक डीआरवाई आधार पर, केवल (ए) सामान्य 'नेमस्पेस' के सहज ज्ञान युक्त समानताएं और विशेष रूप से (बी) 'टेम्पलेट' कार्यों को कार्यान्वित करने के बारे में सोचें, जो कि परेशान है। –

4

कोई नहीं है। कम से कम नहीं। आप प्रीप्रोसेसर चाल के लिए जा सकते हैं, लेकिन इसे न करें।

#define IMPL Graph:: 

IMPL Graph(int n){} 
void IMPL printGraph(){} 
void IMPL addEdge(){} 
void IMPL removeEdge(){} 

इसके अलावा, आप भी यह करने के लिए नहीं करना चाहिए। क्या बात है। सी ++ नियम होने के अलावा, यह आपको यह बताने देता है कि आप वास्तव में सदस्य फ़ंक्शन को कार्यान्वित कर रहे हैं।

+1

एह, क्या यह वाकई बुद्धिमान है कि "ऐसा मत करो ... यहाँ कैसे है!"? – GManNickG

+2

@GManNickG मुझे ऐसा लगता है, हाँ। मैं व्यक्तिगत रूप से यह सामान जानना पसंद करता हूं ... –

+3

आप उन्हें एक अलग फ़ाइल में भी परिभाषित कर सकते हैं और कक्षा के शरीर में उन्हें शामिल कर सकते हैं। – Pubby

2

यदि आप पूछ रहे हैं कि क्या आप कक्षा नाम योग्यता निर्दिष्ट किए बिना Graph::printGraph जैसे सदस्य फ़ंक्शन को परिभाषित कर सकते हैं, तो उत्तर नहीं है, वैसे भी आप जिस तरह से चाहते हैं। यह सी में संभव नहीं है ++:

कार्यान्वयन फ़ाइल:

void printEdge(){}; 

ऊपर ठीक संकलन होगा, लेकिन यह आप क्या चाहते हैं नहीं करेंगे। यह Graph कक्षा के भीतर उसी नाम से सदस्य फ़ंक्शन को परिभाषित नहीं करेगा। इसके बजाय, यह printEdge नामक एक नए मुक्त फ़ंक्शन को घोषित और परिभाषित करेगा।

यह अच्छा और उचित है, यदि आपके दृष्टिकोण को थोड़ा दर्द होता है, क्योंकि आप केवल एक ही नाम के साथ दो कार्यों को अलग-अलग स्कॉप्स में चाहते हैं। विचार करें:

// Header File 
class A 
{ 
    void foo(); 
}; 

class B 
{ 
    void foo(); 
}; 

void foo(); 

// Implementation File 
void foo() 
{ 
} 

परिभाषा किस परिभाषा पर लागू होनी चाहिए? सी ++ आपको विभिन्न स्कॉप्स में समान नामों के साथ अलग-अलग फ़ंक्शंस रखने से प्रतिबंधित नहीं करता है, इसलिए आपको संकलक को यह बताना होगा कि आप किस कार्य को परिभाषित कर रहे हैं।

0

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

सरल उत्तर: आप C++ विभाजित कर सकते हैं - फ़ाइल, लेकिन आप विभाजित नहीं कर सकते ऊपर हेडर-फाइलें।

कारण काफी सरल है। जब भी आपके कंपाइलर को एक कन्स्ट्रक्टर को संकलित करने की आवश्यकता होती है, तो उसे यह पता होना चाहिए कि इस तरह के ऑब्जेक्ट को आवंटित करने के लिए कितनी मेमोरी की आवश्यकता है।

उदाहरण के लिए

:

class Foo { 
    double bar; //8 bytes 
    int goo; //4 bytes 
} 

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

उदाहरण के लिए:

h1.h:

class Foo { 
    double bar; //8 bytes 
    int goo; //4 bytes 
} 

h2.h: #include "h1.h"

class Foo { 
    double goo; //8 bytes 
}// we extend foo with a double. 

foo1.cpp:

#include "foo1.h" 

Foo *makeFoo() { 
    return new Foo(); 

} 

foo2.cpp:

#include "foo2.h" 

void cleanupFoo(Foo *foo) { 
    delete foo; 
} 

foo1.h:

#include "h1.h" 

Foo *makeFoo(); 

foo2.h:

#include "h1.h" 
#include "h2.h" 

void cleanupFoo(Foo *foo) 

main.cpp:

#include foo1.h 
#include foo2.h 

void main() { 
    Foo *foo = makeFoo(); 
    cleanupFoo(foo); 
} 
अब

बहुत सावधानी से जाँच करता है, तो आप पहली बार संकलन क्या होता है main.cpp से main.o, फिर foo1.cpp से foo1.o और foo2.cpp foo2.o, और fi उन सभी को एक साथ लिंक करें। इसे संकलित करना चाहिए, लेकिन makeFoo() कुछ और आवंटित करता है तो cleanupFoo() को हटा दिया जाता है।

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

1
 //yes it is possible using preprocessor like this: 

     #define $ ClassName //in .cpp 

    void $::Method1() 
    { 
    } 

    //or like this: in the header .h: 

     #undef $ 
     #define $ ClassName' 

// but you have to include the class header in last #include in your .cpp: 

     #include "truc.h" 
     #include "bidule.h" ... 
     #include "classname.h" 

     void $::Method() { } 

     //i was using also 
     #define $$ BaseClass 
     //with single inheritance than i can do this: 

     void $::Method() 
     { 
     $$::Method(); //call base class method 
     } 

     //but with a typedef defined into class like this it's better to do this: 
     class Derived : Base 
     { 
     typedef Base $$; 

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