"फ़ील्ड में अपूर्ण प्रकार है" त्रुटि


79

मेरी हेडर फ़ाइल में कोई त्रुटि है:

field "ui" has incomplete type.

मैंने uiएक पॉइंटर बनाने की कोशिश की है , लेकिन वह काम नहीं करता है। मुझे नहीं लगता कि मुझे ऐसा करने की आवश्यकता है क्योंकि मैंने पहले ही अपने MainWindowClassनामस्थान में परिभाषित कर लिया है Ui। यह मेरा है mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QtGui/QMainWindow>
#include "ui_mainwindow.h"

namespace Ui {
    class MainWindowClass;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

    public:
        MainWindow(QWidget *parent = 0, Qt::WFlags flags=0);
        ~MainWindow();

    public slots:
        void slideValue(int);
    private:
        Ui::MainWindowClass ui; //error line
};

#endif // MAINWINDOW_H

3
इसके अलावा, यह पूरी तरह से
QtCreator से

जवाबों:


104

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

तो, आप या तो चाहते हैं:

// forward declaration, details unknown
class A;

class B {
  A *a;  // pointer to A, ok
};

या, यदि आप एक सूचक या संदर्भ का उपयोग नहीं कर सकते हैं ...।

// declaration of A
#include "A.h"

class B {
  A a;  // ok, declaration of A is known
};

कुछ बिंदु पर, संकलक के विवरण को जानना आवश्यक है A

यदि आप केवल एक पॉइंटर का भंडारण कर रहे हैं, Aतो आपको घोषणा करते समय उन विवरणों की आवश्यकता नहीं है B। यह उन्हें कुछ बिंदु पर जरूरत है (जब भी आप वास्तव में पॉइंटर को निष्क्रिय करते हैं A), जो संभवतः कार्यान्वयन फ़ाइल में होगा, जहां आपको हेडर को शामिल करना होगा जिसमें वर्ग की घोषणा शामिल है A

// B.h
// header file

// forward declaration, details unknown
class A;

class B {
public: 
    void foo();
private:
  A *a;  // pointer to A, ok
};

// B.cpp
// implementation file

#include "B.h"
#include "A.h"  // declaration of A

B::foo() {
    // here we need to know the declaration of A
    a->whatever();
}

मैं केवल यह जोड़ना चाहूंगा कि आप टेम्प्लेट के माध्यम से एक ही लक्ष्य प्राप्त कर सकते हैं। पहला उदाहरण (rextester.com/TLPEJW28982) ए को वैश्विक वर्ग घोषित करता है और वर्ग टेम्पलेट परिभाषा के बाद इसे परिभाषित करता है। एक लाभ के रूप में, आपको यह चिंता करने की ज़रूरत नहीं है कि आप संरचना ए को कहाँ परिभाषित करते हैं और आप युग्मन से बचते हैं। दूसरा उदाहरण (rextester.com/PJCD69132) A को बी के नेस्टेड स्ट्रक्चर के रूप में मानता है। कारण यह है कि यह कंपाइल और ठीक चलता है क्योंकि टेम्प्लेट करते समय होने वाले टू-फेज लुकअप के कारण होता है। अधिक जानकारी के लिए, कृपया C ++ टेम्प्लेट्स: कम्प्लीट गाइड, 10.3.1 टू-फेज़ लुकअप देखें।
कॉन्स्टैंटिनोस गेलिनोस

20

समस्या यह है कि आपकी uiसंपत्ति वर्ग की एक आगे की घोषणा का उपयोग करती है Ui::MainWindowClass, इसलिए "अपूर्ण प्रकार" त्रुटि।

इसमें हेडर फ़ाइल शामिल है जिसमें यह वर्ग घोषित किया गया है जो समस्या को ठीक करेगा।

संपादित करें

आपकी टिप्पणी के आधार पर, निम्नलिखित कोड:

namespace Ui
{
    class MainWindowClass;
}

एक वर्ग घोषित नहीं करता है । यह एक आगे की घोषणा है , जिसका अर्थ है कि क्लास किसी समय, लिंक समय पर मौजूद होगा।
असल में, यह सिर्फ संकलक को बताता है कि प्रकार मौजूद होगा, और इसके बारे में चेतावनी नहीं दी जानी चाहिए।

लेकिन वर्ग को कहीं न कहीं परिभाषित करना होगा

ध्यान दें कि यह केवल तभी काम कर सकता है जब आपके पास इस प्रकार का एक संकेतक हो।
आपके पास अपूर्ण प्रकार का एक सांख्यिकीय रूप से आवंटित उदाहरण नहीं हो सकता है।

तो या तो आप वास्तव में एक अपूर्ण प्रकार चाहते हैं, और फिर आपको अपने uiसदस्य को सूचक के रूप में घोषित करना चाहिए :

namespace Ui
{
    // Forward declaration - Class will have to exist at link time
    class MainWindowClass;
}

class MainWindow : public QMainWindow
{
    private:

        // Member needs to be a pointer, as it's an incomplete type
        Ui::MainWindowClass * ui;
};

या आप एक सांख्यिकीय रूप से आवंटित उदाहरण चाहते हैं Ui::MainWindowClass, और फिर इसे घोषित करने की आवश्यकता है। आप इसे किसी अन्य हेडर फ़ाइल में कर सकते हैं (आमतौर पर, प्रति क्लास एक हेडर फ़ाइल होती है)।
लेकिन बस कोड को बदलकर:

namespace Ui
{
    // Real class declaration - May/Should be in a specific header file
    class MainWindowClass
    {};
}


class MainWindow : public QMainWindow
{
    private:

        // Member can be statically allocated, as the type is complete
        Ui::MainWindowClass ui;
};

काम भी करेगा।

दोनों घोषणाओं के बीच अंतर पर ध्यान दें। पहले एक आगे की घोषणा का उपयोग करता है, जबकि दूसरा वास्तव में वर्ग की घोषणा करता है (यहां कोई गुण नहीं हैं और न ही विधियां हैं)।


धन्यवाद। यह केवल हेडर फ़ाइल है जो मेरे पास है। मैंने कक्षा को मेनविंडोक्लास घोषित किया है, ठीक # नोटबंदी के बाद। क्या मुझे एक नई हेडर फ़ाइल बनानी चाहिए?
इसाबेलाव

कोई आगे की घोषणा नहीं है, समस्या उसी प्रकार के सदस्य चर को घोषित कर रही है जिसे वर्तमान में परिभाषित किया जा रहा है।
एड एस।

कोई बात नहीं, मैं घुंघराले ब्रेसिज़ पर खो गया, यह नहीं देखा कि यह वास्तव में आगे की घोषणा के नीचे घोषित एक वर्ग था MainWindowClass
एड एस।

Ui::MainWindowClass(सदस्य चर) में परिभाषित किया गया है MainWindow। वास्तव में एक ही तरह का नहीं।
मैकडेम

हालाँकि, मैं यह नहीं कहूंगा कि यदि आप एक फॉरवर्ड डिक्लेरेशन का उपयोग कर रहे हैं, तो वेरिएबल को पॉइंटर या फॉरवर्ड डिक्लेयर टाइप का संदर्भ होना चाहिए। अन्यथा, यदि यह अस्वीकार्य है, तो आपको हेडर को शामिल करने की आवश्यकता है जिसमें प्रकार की घोषणा शामिल है।
एड एस।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.