2016-10-26 7 views
18

मैं utilA.cpp में निम्नलिखित कोड का टुकड़ा होगा:सी ++ में यह आगे की घोषणा क्यों है?

// utilB.h 
namespace xm 
{ 
    void zoo(struct tm timeval); //<-----line 0 
} 


// utilA.cpp 
#include <utilB.h>     //<----line 1 
#include <time.h>     //<----line 2 
namespace xm 
{ 
    void foo() 
    { 
     struct tm time1 = {0}; //<----line 3 
    } 
} 

जीसीसी की शिकायत जब utilA.cpp संकलन,

error: variable 'xm::tm time1' has initializer but incomplete type 

ऐसा लगता है इस वजह से utilA.h लाइन 0 में struct tm उपयोग कर रहा है, लेकिन time.h शामिल किए बिना, और संकलक struct tm को आगे घोषित करने के रूप में 0 0 में struct tm का इलाज करता है, इसलिए struct tm लाइन 2 पर xm::tm को 0 0 पर शीर्षलेख के अंदर हल किया गया है।

तो क्या सी ++ मानक आगे 0 घोषणा के रूप में इस struct tm को फ़ंक्शन पैरामीटर के रूप में परिभाषित करता है? कृपया इसे समझाने में मदद करें और मानक से उद्धरण सहायक होंगे।

+6

अपने शीर्षलेख में '# शामिल करें ' लिखें क्योंकि आपका हेडर इस पर निर्भर करता है। – molbdnilo

+0

हां, हमें utb.h में #in32e जोड़ना चाहिए, लेकिन चूंकि यह एक विशाल प्रोजेक्ट से कोड स्निपेट है, इसलिए हमें रूट कारण खोजने से पहले हमें बहुत उलझन में डाल दिया गया। – ZijingWu

+0

यह प्रोग्रामिंग की बहुत खराब शैली है। अनदेखी करो इसे। पीएस: क्या आपने शीर्ष पर '# include'-s को स्थानांतरित करने का प्रयास किया है? – i486

उत्तर

20

लाइन 0 में, आपने नामक एक वर्ग घोषित किया है जो xm नामस्थान के अंदर है। हां, सी ++ फंक्शन/टेम्पलेट पैरामीटर में घोषित प्रकारों की अनुमति देता है।

N4140 § 3.4.4 [basic.lookup.elab]/2

सविस्तार-प्रकार-विनिर्देशक द्वारा शुरू की गई है, तो वर्ग-कुंजी और इस देखने एक नहीं मिल रहा है पहले से प्रकार- नाम घोषित, या यदि सविस्तार-प्रकार-विनिर्देशक फार्म के साथ एक घोषणा में प्रकट होता है:

वर्ग ke वाई विशेषता-विनिर्देशक-सीईसी ऑप्ट पहचानकर्ता;

विस्तारित-प्रकार-विनिर्देश एक घोषणा है जो 3.312 में वर्णित वर्ग-नाम प्रस्तुत करती है।

क्योंकि आप एक वर्ग xm नाम स्थान के अंदर tm नामित घोषित कर दिया, यह पहली बार ऐसा नाम है जो नाम लुकअप लाइन 3. ::tm (और ::std::tm) में tm के लिए पाता नहीं माना जाता है। और चूंकि कक्षा ::xm::tm की कोई परिभाषा नहीं है, इसलिए संकलक इसके बारे में शिकायत करता है कि यह अधूरा प्रकार है।

आप सी ++ में सी कोड लिखने नहीं कर रहे थे, तो आप की तरह

struct tm; 

namespace xz{ 
    void zoo(tm timeval); 
} 

या

#include <ctime> 

namespace xz{ 
    void zoo(tm timeval); 
} 

कुछ लिखना चाहते हैं और आपको लगता है कि समस्या नहीं होती।

याद रखें कि आप नहीं नाम नाम स्थान एसटीडी में आगे की घोषणा कर सकते हैं

7

तो सी ++ मानक आगे घोषणा के रूप में समारोह पैरामीटर के एक प्रकार के रूप में इस struct tm को परिभाषित करता है। कृपया इसे समझाने में मदद करें और मानक से कोटा उपयोगी होगा।

हाँ, struct tm timeval यहाँ एक नया वर्ग नाम xm::tm का परिचय देंगे।


(स्पष्टीकरण और उद्धरण)

struct tm एक elaborated type specifier है, जो एक नया वर्ग के नाम पेश करने का इस्तेमाल किया जा सकता है।

$3.1/4 Declarations and definitions [basic.def]

[ध्यान दें: एक वर्ग के नाम भी परोक्ष एक सविस्तार-प्रकार-विनिर्देशक द्वारा घोषित किया जा सकता है ([dcl.type.elab])। - अंत टिप्पणी]

$9.1/2 Class names [class.name]:

वर्ग-कुंजी पहचानकर्ता के लिए पूरी तरह से मिलकर एक घोषणा; या तो वर्तमान दायरे में नाम का पुनर्विक्रय या आगे के नाम के रूप में पहचानकर्ता की घोषणा है। यह वर्तमान क्षेत्र में कक्षा नाम प्रस्तुत करता है।

$3.4.4/2 Elaborated type specifiers [basic.lookup.elab]:

या सविस्तार-प्रकार-विनिर्देशक फार्म के साथ एक घोषणा में दिखाई देता है:

class-key attribute-specifier-seqopt identifier ; 

सविस्तार-प्रकार-विनिर्देशक एक घोषणा है कि परिचय है वर्ग-नाम जैसा कि [basic.scope.pdecl] में वर्णित है।

$3.3.2/7 Point of declaration [basic.scope.pdecl]:

अगर सविस्तार-प्रकार-विनिर्देशक-सेक डीईसीएल-विनिर्देशक या एक समारोह नाम स्थान दायरे में परिभाषित की पैरामीटर-घोषणा-खंड में प्रयोग किया जाता है, पहचानकर्ता घोषित किया जाता है नामस्थान में कक्षा-नाम के रूप में में घोषणा शामिल है;

struct tm timeval समारोह पैरामीटर घोषणा के रूप में इस्तेमाल के लिए, क्योंकि <time.h> शामिल नहीं है और अभी भी कोई वर्ग tm नाम है, वर्ग tm वर्तमान क्षेत्र (अर्थात नाम स्थान xm) में घोषित किया जाएगा है, तो xm::tm आगे घोषित किया जाएगा।

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