2012-11-28 14 views
5

मेरे पास कई वर्गों के साथ एक क्यूटी अनुप्रयोग है जो सिग्नल और स्लॉट का उपयोग करता है और यह ठीक से संकलित करता है। हालांकि, जब मैं मुख्य CPP (main.cpp) फ़ाइल के अंदर एक कस्टम क्लास बना देता हूं, तो मुझे एक लिंकर त्रुटि मिलती है।क्यूटी सिग्नल/स्लॉट उदाहरण के साथ लिंकर त्रुटि

Error 4 error LNK2001: unresolved external symbol "public: virtual struct QMetaObject const * __thiscall Counter::metaObject(void)const " ([email protected]@@[email protected]@XZ) 
Error 5 error LNK2001: unresolved external symbol "public: virtual void * __thiscall Counter::qt_metacast(char const *)" ([email protected]@@[email protected]) 
Error 6 error LNK2001: unresolved external symbol "public: virtual int __thiscall Counter::qt_metacall(enum QMetaObject::Call,int,void * *)" ([email protected]@@[email protected]@@[email protected]) 
Error 7 error LNK2019: unresolved external symbol "protected: void __thiscall Counter::valueChanged(int)" ([email protected]@@[email protected]) referenced in function "public: void __thiscall Counter::setValue(int)" ([email protected]@@[email protected]) 

यह लिंकर त्रुटि नहीं होती है जब मैं एक अलग हेडर फाइल में काउंटर जगह: यहाँ त्रुटियाँ हैं

class Counter : public QObject 
{ 
    Q_OBJECT 

public: 
    Counter() { m_value = 0; } 

    int value() const { return m_value; } 

public slots: 
    void setValue(int value) 
    { 
    if(value!=m_value) 
    { 
     m_value = value; 
     qDebug() << "Value " << value; 
     emit valueChanged(value); 
    } 
    } 

signals: 
    void valueChanged(int newValue); 

private: 
    int m_value; 
}; 

int main(int argc, char *argv[]) 
{ 
    QCoreApplication app(argc, argv); 
    Counter a, b; 
    QObject::connect(&a, SIGNAL(valueChanged(int)), &b, SLOT(setValue(int))); 

    a.setValue(12);  // a.value() == 12, b.value() == 12 
    b.setValue(48);  // a.value() == 12, b.value() == 48 

    QTimer::singleShot(0, &app, SLOT(quit())); 

    return app.exec(); 
} 

:

यहाँ कोड मैं का उपयोग करें। इस व्यवहार का कारण क्या है?

उत्तर

5

मुझे लगता है कि आप qmake के साथ काम कर रहे हैं।

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

आपको qmake को सूचित करना होगा कि फ़ाइल में एक वर्ग है। ऐसा करने के लिए, Counter की घोषणा के बाद #include "filename.moc" डालें। आप अधिक जानकारी here (QtCentre) या here (doc) देख सकते हैं।

आप qmake से एक और उपकरण के साथ काम कर रहे हैं, CMake कहते हैं, आप .cpp फ़ाइलें (सरल उन सब को कार्रवाई करने के लिए है) पार्स करने के लिए MOC मजबूर करने के लिए एक नियम निर्दिष्ट करना होगा। उन फ़ाइलों के लिए जिनमें Qt ऑब्जेक्ट क्लास नहीं है, moc एक खाली फ़ाइल उत्पन्न करेगा।

हालांकि, अगर इस वर्ग को 'निजी' बनाया गया है, तो भी मैं आपको हेडर में घोषित करने की सलाह देता हूं (उदाहरण के लिए counter_private.h)। उदाहरण के लिए, क्यूटी स्रोत इस चाल का उपयोग कर रहा है।

1

वे एमओसी/यूआईसी कस्टम निर्माण आदेश, हेडर फाइल पर किया जाता है तो यह संकलित जब एक अलग शीर्ष लेख/स्रोत फ़ाइल में डाल दिया और नहीं है जब एक ही स्रोत फ़ाइल में डाल

2

ऐसा लगता है कि आप केवल है एक कोड फ़ाइल। यदि आप क्यूटी प्रोजेक्ट बिल्ड (qmake & & मेक या क्यूटीक्रिएटर) बनाने के लिए डिफ़ॉल्ट तरीके का उपयोग करते हैं, तो एमओसी केवल * .h फ़ाइलों को स्कैन करता है। यदि आपके पास अपना सभी कोड एक main.cpp में है तो एमओसी कोई कोड नहीं बनाएगा, लेकिन काम करने के लिए सिग्नल/स्लॉट के लिए इसकी आवश्यकता है।

इस विशिष्ट उदाहरण को काम करने का सबसे आसान तरीका आपके main.cpp के अंत में "# शामिल" main.moc "जोड़ देगा। यह निर्भरता qmake द्वारा पता लगाया जाएगा और आवश्यक मेकफ़ाइल लक्ष्य बनाए जाएंगे।

सबसे प्यारा तरीका साफ होगा: एक वर्ग - एक शीर्षलेख और एक कार्यान्वयन फ़ाइल।

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