2010-01-25 11 views
86

"एक प्रकार का नाम नहीं है" मैं दो वर्गों नीचे के रूप में घोषित किया है:त्रुटि

MyMessageBox does not name a type

+10

अंतहीन समय मैं इस त्रुटि को जाता हूं, केवल यह समझने के लिए कि आईडीई द्वारा उत्पन्न आयात गार्ड डुप्लिकेट किए गए हैं – Mazyod

+0

ध्यान दें कि यदि आप एक .h/.hpp फ़ाइल में घोषणा के लिए बाहरी संदर्भ देते हैं तो आप यह त्रुटि भी प्राप्त कर सकते हैं वर्ग परिभाषित होने से पहले, जब भी आपके पास .cpp फ़ाइल के भीतर .h/.hpp समावेशन के बाद वास्तविक घोषणा होती है। – Owl

+0

@ मैज़्योद। शुक्रिया शुक्रिया। मैं यह पता नहीं लगा सका कि बिल्ली इस अजीब त्रुटि का कारण बन रहा था। –

उत्तर

160

जब:

class User 
{ 
public: 
    MyMessageBox dataMsgBox; 
}; 

class MyMessageBox 
{ 
public: 
    void sendMessage(Message *msg, User *recvr); 
    Message receiveMessage(); 
    vector<Message> *dataMessageList; 
}; 

जब मैंने इसे जीसीसी का उपयोग कर संकलित करने के लिए प्रयास करते हैं, यह निम्नलिखित त्रुटि देता है संकलक वर्ग User संकलित करता है और MyMessageBox लाइन पर जाता है, MyMessageBox अभी तक परिभाषित नहीं किया गया है। कंपाइलर को कोई विचार नहीं है MyMessageBox मौजूद है, इसलिए आपके क्लास सदस्य के अर्थ को समझ नहीं आ रहा है।

आपको यह सुनिश्चित करना होगा कि से पहले परिभाषित किया गया है, तो आप इसे सदस्य के रूप में उपयोग करते हैं। यह परिभाषा आदेश को उलटकर हल किया जाता है। हालांकि, आपके पास चक्रीय निर्भरता है: यदि आप MyMessageBoxUser से ऊपर ले जाते हैं, तो MyMessageBox की परिभाषा में User नाम परिभाषित नहीं किया जाएगा!

आप क्या कर सकते हैं आगे घोषितUser; यानी, इसे घोषित करें लेकिन इसे परिभाषित न करें। संकलन के दौरान, एक प्रकार जिसे घोषित किया गया है लेकिन परिभाषित नहीं किया गया है उसे अधूरा प्रकार कहा जाता है। सरल उदाहरण पर विचार करें:

struct foo; // foo is *declared* to be a struct, but that struct is not yet defined 

struct bar 
{ 
    // this is okay, it's just a pointer; 
    // we can point to something without knowing how that something is defined 
    foo* fp; 

    // likewise, we can form a reference to it 
    void some_func(foo& fr); 

    // but this would be an error, as before, because it requires a definition 
    /* foo fooMember; */ 
}; 

struct foo // okay, now define foo! 
{ 
    int fooInt; 
    double fooDouble; 
}; 

void bar::some_func(foo& fr) 
{ 
    // now that foo is defined, we can read that reference: 
    fr.fooInt = 111605; 
    fr.foDouble = 123.456; 
} 

आगे User घोषित करने से, MyMessageBox अभी भी यह करने के लिए एक सूचक या संदर्भ के रूप में कर सकते हैं:

class User; // let the compiler know such a class will be defined 

class MyMessageBox 
{ 
public: 
    // this is ok, no definitions needed yet for User (or Message) 
    void sendMessage(Message *msg, User *recvr); 

    Message receiveMessage(); 
    vector<Message>* dataMessageList; 
}; 

class User 
{ 
public: 
    // also ok, since it's now defined 
    MyMessageBox dataMsgBox; 
}; 

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

class MyMessageBox; 

class User 
{ 
public: 
    // size not available! it's an incomplete type 
    MyMessageBox dataMsgBox; 
}; 

यह कार्य नहीं करेगा , क्योंकि यह अभी तक आकार नहीं जानता है।


एक तरफ ध्यान दें पर, यह समारोह:

void sendMessage(Message *msg, User *recvr); 

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

बल्कि, एक संदर्भ (संभवतः स्थिरांक) का उपयोग (शून्य एक पूरी तरह से वैध सूचक मूल्य है!):

void sendMessage(const Message& msg, User& recvr); 
+1

+1 आज कुछ सीख लिया - मैंने सोचा कि 'MyMessageBox' घोषित करने के लिए पर्याप्त होगा। क्या होगा यदि 'MyMessageBox' में 'उपयोगकर्ता' प्रकार का चर भी था - क्या यह एक डेडलॉक होगा? – Amarghosh

+9

@ अमरोश: हाँ, यह असंभव होगा। तर्कसंगत रूप से असंभव है, क्योंकि 'उपयोगकर्ता' में 'संदेशबॉक्स' होगा जिसमें 'उपयोगकर्ता' होगा, जिसमें 'संदेशबॉक्स' होगा जिसमें 'उपयोगकर्ता' होगा, जिसमें 'संदेशबॉक्स' होगा जिसमें ' उपयोगकर्ता', जिसमें 'MessageBox' होगा जिसमें 'उपयोगकर्ता' होगा ... – GManNickG

+0

धन्यवाद जीएमएन। जैसा कि आपने सुझाव दिया है मैंने अपने कोड में बदलाव किए हैं और यह अभी ठीक काम करता है। –

0

आप घोषित करना चाहिए प्रोटोटाइप यह उपयोग करने से पहले:

class User; 

class MyMessageBox 
{ 
public: 
void sendMessage(Message *msg, User *recvr); 
Message receiveMessage(); 
vector<Message> *dataMessageList; 
}; 

class User 
{ 
public: 
MyMessageBox dataMsgBox; 
}; 

संपादित: बदली प्रकार

+1

नहीं, काम नहीं करेगा। कक्षा के सदस्यों को परिभाषित किया जाना चाहिए, घोषित नहीं किया गया है। – MSalters

2

सी ++ compilers की प्रक्रिया आईआर इनपुट एक बार। आपके द्वारा उपयोग की जाने वाली प्रत्येक कक्षा को पहले परिभाषित किया जाना चाहिए था। इससे पहले कि आप इसे परिभाषित करने से पहले MyMessageBox का उपयोग करें। इस मामले में, आप बस दो वर्ग परिभाषाओं को स्वैप कर सकते हैं।

+0

स्वैपिंग 'MyMessageBox' के रूप में काम नहीं करेगा, इसकी विधि घोषणा में' उपयोगकर्ता' प्रकार है। – Amarghosh

+0

काम न करें क्योंकि MyMessageBox उपयोगकर्ता वर्ग का भी उपयोग करता है। –

+0

असल में, यह परिभाषा _use_ वर्ग 'उपयोगकर्ता' नहीं है। महत्वपूर्ण भेद, क्योंकि इसका मतलब क्लास उपयोगकर्ता को उस बिंदु पर _declared_ होना चाहिए, _defined_ नहीं। लेकिन जीएमएन की व्यापक पोस्ट देखें। – MSalters

6
  1. फॉरवर्ड घोषित उपयोगकर्ता
  2. उपयोगकर्ता से पहले MyMessageBox की घोषणा रखो
2

आप उपयोगकर्ता से पहले MyMessageBox परिभाषित करने की जरूरत - क्योंकि उपयोगकर्ता मूल्य द्वारा MyMessageBox की वस्तु में शामिल हैं (और इसलिए संकलक पता होना चाहिए इसका माप)।

इसके अलावा आपको घोषित करने की आवश्यकता होगी उपयोगकर्ता MyMessageBox - क्योंकि MyMessageBox में उपयोगकर्ता * प्रकार का सदस्य शामिल है।

2

एक संबंधित नोट पर, यदि आप था:

class User; // let the compiler know such a class will be defined 

    class MyMessageBox 
    { 
    public: 
     User* myUser; 
    }; 

    class User 
    { 
    public: 
     // also ok, since it's now defined 
     MyMessageBox dataMsgBox; 
    }; 

तो वह भी काम करेगा, क्योंकि उपयोगकर्ता एक सूचक

+0

आगे की घोषणा शब्द है – benziv

0

यह हमेशा C++ यदि आपके पास यह है कि प्रोत्साहित किया जाता है के रूप में MyMessageBox में परिभाषित किया गया है श्रेणी प्रति हेडर फ़ाइल, इस चर्चा को SO [1] में देखें। जीएमएनएनजीजी उत्तर बताता है कि ऐसा क्यों होता है। लेकिन इसे हल करने का सबसे अच्छा तरीका है User कक्षा एक हेडर फ़ाइल (User.h) और MyMessageBox कक्षा में किसी अन्य शीर्षलेख फ़ाइल (MyMessageBox.h) में रखना है। फिर आपके User.h में आप MyMessageBox.h और MyMessageBox.h में User.h शामिल हैं। "गौड्स शामिल करें" को न भूलें [2] ताकि आपका कोड सफलतापूर्वक संकलित हो।