2013-02-25 103 views
1

我有兩個類(或更好的,頭文件),這是我的C++程序的一部分,我根本無法使這一切工作!作爲我的應用程序的一部分,它們基本上需要彼此的數據才能正常運行。C++前向聲明和'不完整的類型是不允許的'錯誤

不要通過閱讀本代碼的肉來折磨自己;我只需要轉發聲明相互包含問題已解決,因此只需查看代碼中與此問題有關的那些部分。

錯誤發生在第二個代碼段中,最後(我不得不從第一個代碼片斷掉一大塊代碼,所以我可以發佈這個問題,我想這與我的問題無關)。

introForm.h

#pragma once 
#include <stdlib.h> 
#include "creditsForm.h" 
#include "registerForm.h" 
#include "aboutForm.h" 
#include "QuizForm.h" 
#include <windows.h> 
#include <time.h> 
#ifndef __introForm__H__ 
#define __introForm__H__ 

namespace InteractiveQuiz { 

    using namespace System; 
    using namespace System::ComponentModel; 
    using namespace System::Collections; 
    using namespace System::Windows::Forms; 
    using namespace System::Data; 
    using namespace System::Drawing; 

    ref class QuizForm; 

    /// <summary> 
    /// Summary for introForm 
    /// </summary> 
    public ref class introForm : public System::Windows::Forms::Form 
    { 
    public: 
     introForm(void) 
     { 
      InitializeComponent(); 
      // 
      //TODO: Add the constructor code here 
      // 
     } 

    protected: 
     /// <summary> 
     /// Clean up any resources being used. 
     /// </summary> 
     ~introForm() 
     { 
      if (components) 
      { 
       delete components; 
      } 
     } 

     // Extracts a word from a sentence with a given ordinal number 
     string extractWord(int ordinal, string sentence) 
     { 
      int counter = 0; 
      string word; 

      for (int i = 0; i < sentence.length(); i++) 
      { 
       if (sentence[i] == ',') 
       { 
        if (sentence [i+1] != ',') 
        { 
         counter ++; 

         if (counter == ordinal) 
         { 
          return word; 
         } 

         word =""; 
        } 
       } 
       else 
       { 
        word += sentence[i]; 
       }  
      } 
     } 

private: System::Void btnExit1_Click(System::Object^ sender, System::EventArgs^ e) { 
      exit(1); 
     } 
private: System::Void btnCredits1_Click(System::Object^ sender, System::EventArgs^ e) { 
      creditsForm^ credits = gcnew creditsForm; 
      credits->Show(); 
     } 
private: System::Void registerBtn_Click(System::Object^ sender, System::EventArgs^ e) { 
      registerForm^ registerUser = gcnew registerForm; 
      registerUser->Show(); 
     } 
private: System::Void aboutToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) { 
      aboutForm^ aboutApp = gcnew aboutForm; 
      aboutApp->Show(); 
     } 
private: System::Void quitToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) { 
      introForm::Close(); 
     } 
private: System::Void introForm_Load(System::Object^ sender, System::EventArgs^ e) { 
      ifstream regUsers ("regUsers.csv"); 

      if (regUsers) 
      { 
       lblUser->Enabled = true; 
       lblPass->Enabled = true; 

       logUsername->Enabled = true; 
       logPassword->Enabled = true; 

       btnLogSubmit->Enabled = true; 
       if (lblLogin->Text == L"Not logged in") 
       { 
        quizLogo->Visible = false; 
       } 
      } 
      else 
      { 
       lblUser->Enabled = false; 
       lblPass->Enabled = false; 

       logUsername->Enabled = false; 
       logPassword->Enabled = false; 

       btnLogSubmit->Enabled = false; 

       quizLogo->Visible = true; 
      } 

      regUsers.close(); 
     } 

public: String^ loggedUser; 

private: System::Void btnLogSubmit_Click(System::Object^ sender, System::EventArgs^ e) { 
      if (logUsername->Text->Length < 6 && logPassword->Text->Length < 8) 
      { 
       errorLabel->Text = L"Username must be at least 6 and password 8 characters long!"; 
       errorLabel->Visible = true; 
      } 
      else if (logUsername->Text->Length < 6) 
      { 
       errorLabel->Text = L"Username must be at least 6 characters long!"; 
       errorLabel->Visible = true; 
      } 
      else if (logUsername->Text->Contains(" ")) 
      { 
       errorLabel->Text = L"Username must not contain spaces!"; 
       errorLabel->Visible = true; 
      } 
      else if (logPassword->Text->Length < 8) 
      { 
       errorLabel->Text = L"Password must be at least 8 characters long!"; 
       errorLabel->Visible = true; 
      } 
      if (logUsername->Text->Length >= 6 && logPassword->Text->Length >= 8) 
      { 
       String^ result = logUsername->Text + "," + logPassword->Text; 
       string result2 = marshal_as<string>(result); 

       ifstream regUsers("regUsers.csv"); 
       string line; 
       string fileUserPass; 

       /* While there is still a line. */ 
       while(getline(regUsers, line)) 
       { 
        fileUserPass = extractWord(1, line) + "," + extractWord(2,line); 

        if (fileUserPass == result2) // Successful login 
        { 
         lblLogin->Text = L"Logged in as " + logUsername->Text; 

         quizLogo->Visible = true; 
         errorLabel->Visible = false; 

         btnLogout->Enabled = true; 

         startNewToolStripMenuItem->Enabled = true; 

         loggedUser = logUsername->Text; 
        } 
       } 

       regUsers.close(); 

       if (fileUserPass != result2) 
       { 
        errorLabel->Text = L"Username or password incorrect!"; 
        errorLabel->Visible = true; 
       } 
      } 
     } 
private: System::Void btnLogout_Click(System::Object^ sender, System::EventArgs^ e) { 
      btnLogout->Enabled = false; 

      lblLogin->Text = L"Not logged in"; 

      quizLogo->Visible = false; 

      errorLabel->Visible = false; 

      logUsername->Clear(); 
      logPassword->Clear(); 

      logUsername->Focus(); 

      startNewToolStripMenuItem->Enabled = false; 
     } 
private: System::Void startNewToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) { 
      QuizForm^ quiz = gcnew QuizForm; 
      quiz->Show(); 
     } 
}; 
} 

#endif // !__introForm__H__ 

QuizForm.h

#pragma once 
#include <string.h> 
using namespace std; 

#ifndef __QuizForm__H__ 
#define __QuizForm__H__ 

namespace InteractiveQuiz { 

    using namespace System; 
    using namespace System::ComponentModel; 
    using namespace System::Collections; 
    using namespace System::Windows::Forms; 
    using namespace System::Data; 
    using namespace System::Drawing; 

    ref class introForm; 

    /// <summary> 
    /// Summary for QuizForm 
    /// </summary> 
    public ref class QuizForm : public System::Windows::Forms::Form 
    { 
    public: 
     QuizForm(void) 
     { 
      InitializeComponent(); 
      // 
      //TODO: Add the constructor code here 
      // 
     } 


    protected: 
     /// <summary> 
     /// Clean up any resources being used. 
     /// </summary> 
     ~QuizForm() 
     { 
      if (components) 
      { 
       delete components; 
      } 
     } 
    private: System::Windows::Forms::TabControl^ tabControl; 
    protected: 

    protected: 
    private: System::Windows::Forms::TabPage^ tabPage1; 
    private: System::Windows::Forms::TabPage^ tabPage2; 
    private: System::Windows::Forms::MenuStrip^ menuStrip1; 
    private: System::Windows::Forms::Button^ button1; 
    private: System::Windows::Forms::ToolStripMenuItem^ quizToolStripMenuItem; 
    private: System::Windows::Forms::ToolStripMenuItem^ startNewToolStripMenuItem; 
    private: System::Windows::Forms::ToolStripMenuItem^ endQuizToolStripMenuItem; 
    private: System::Windows::Forms::ToolStripSeparator^ toolStripSeparator1; 
    private: System::Windows::Forms::ToolStripMenuItem^ quitToolStripMenuItem; 
    private: System::Windows::Forms::ToolStripMenuItem^ helpToolStripMenuItem; 
    private: System::Windows::Forms::ToolStripMenuItem^ aboutToolStripMenuItem; 
    private: System::Windows::Forms::Label^ lblQuizLogin; 


    private: 
     /// <summary> 
     /// Required designer variable. 
     /// </summary> 
     System::ComponentModel::Container ^components; 

#pragma region Windows Form Designer generated code 
     /// <summary> 
     /// Required method for Designer support - do not modify 
     /// the contents of this method with the code editor. 
     /// </summary> 
     void InitializeComponent(void) 
     { 
      this->tabControl = (gcnew System::Windows::Forms::TabControl()); 
      this->tabPage1 = (gcnew System::Windows::Forms::TabPage()); 
      this->tabPage2 = (gcnew System::Windows::Forms::TabPage()); 
      this->menuStrip1 = (gcnew System::Windows::Forms::MenuStrip()); 
      this->quizToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem()); 
      this->startNewToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem()); 
      this->endQuizToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem()); 
      this->toolStripSeparator1 = (gcnew System::Windows::Forms::ToolStripSeparator()); 
      this->quitToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem()); 
      this->helpToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem()); 
      this->aboutToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem()); 
      this->button1 = (gcnew System::Windows::Forms::Button()); 
      this->lblQuizLogin = (gcnew System::Windows::Forms::Label()); 
      this->tabControl->SuspendLayout(); 
      this->menuStrip1->SuspendLayout(); 
      this->SuspendLayout(); 
      // 
      // tabControl 
      // 
      this->tabControl->Controls->Add(this->tabPage1); 
      this->tabControl->Controls->Add(this->tabPage2); 
      this->tabControl->Location = System::Drawing::Point(12, 27); 
      this->tabControl->Name = L"tabControl"; 
      this->tabControl->SelectedIndex = 0; 
      this->tabControl->Size = System::Drawing::Size(686, 430); 
      this->tabControl->TabIndex = 0; 
      // 
      // tabPage1 
      // 
      this->tabPage1->Location = System::Drawing::Point(4, 22); 
      this->tabPage1->Name = L"tabPage1"; 
      this->tabPage1->Padding = System::Windows::Forms::Padding(3); 
      this->tabPage1->Size = System::Drawing::Size(678, 404); 
      this->tabPage1->TabIndex = 0; 
      this->tabPage1->Text = L"tabPage1"; 
      this->tabPage1->UseVisualStyleBackColor = true; 
      // 
      // tabPage2 
      // 
      this->tabPage2->Location = System::Drawing::Point(4, 22); 
      this->tabPage2->Name = L"tabPage2"; 
      this->tabPage2->Padding = System::Windows::Forms::Padding(3); 
      this->tabPage2->Size = System::Drawing::Size(678, 404); 
      this->tabPage2->TabIndex = 1; 
      this->tabPage2->Text = L"tabPage2"; 
      this->tabPage2->UseVisualStyleBackColor = true; 
      // 
      // menuStrip1 
      // 
      this->menuStrip1->Items->AddRange(gcnew cli::array<System::Windows::Forms::ToolStripItem^>(2) {this->quizToolStripMenuItem, 
       this->helpToolStripMenuItem}); 
      this->menuStrip1->Location = System::Drawing::Point(0, 0); 
      this->menuStrip1->Name = L"menuStrip1"; 
      this->menuStrip1->Size = System::Drawing::Size(710, 24); 
      this->menuStrip1->TabIndex = 1; 
      this->menuStrip1->Text = L"menuStrip1"; 
      // 
      // quizToolStripMenuItem 
      // 
      this->quizToolStripMenuItem->DropDownItems->AddRange(gcnew cli::array<System::Windows::Forms::ToolStripItem^>(4) {this->startNewToolStripMenuItem, 
       this->endQuizToolStripMenuItem, this->toolStripSeparator1, this->quitToolStripMenuItem}); 
      this->quizToolStripMenuItem->Name = L"quizToolStripMenuItem"; 
      this->quizToolStripMenuItem->Size = System::Drawing::Size(43, 20); 
      this->quizToolStripMenuItem->Text = L"&Quiz"; 
      // 
      // startNewToolStripMenuItem 
      // 
      this->startNewToolStripMenuItem->Name = L"startNewToolStripMenuItem"; 
      this->startNewToolStripMenuItem->Size = System::Drawing::Size(125, 22); 
      this->startNewToolStripMenuItem->Text = L"Start &New"; 
      // 
      // endQuizToolStripMenuItem 
      // 
      this->endQuizToolStripMenuItem->Name = L"endQuizToolStripMenuItem"; 
      this->endQuizToolStripMenuItem->Size = System::Drawing::Size(125, 22); 
      this->endQuizToolStripMenuItem->Text = L"&End Quiz"; 
      // 
      // toolStripSeparator1 
      // 
      this->toolStripSeparator1->Name = L"toolStripSeparator1"; 
      this->toolStripSeparator1->Size = System::Drawing::Size(122, 6); 
      // 
      // quitToolStripMenuItem 
      // 
      this->quitToolStripMenuItem->Name = L"quitToolStripMenuItem"; 
      this->quitToolStripMenuItem->Size = System::Drawing::Size(125, 22); 
      this->quitToolStripMenuItem->Text = L"Q&uit"; 
      // 
      // helpToolStripMenuItem 
      // 
      this->helpToolStripMenuItem->DropDownItems->AddRange(gcnew cli::array<System::Windows::Forms::ToolStripItem^>(1) {this->aboutToolStripMenuItem}); 
      this->helpToolStripMenuItem->Name = L"helpToolStripMenuItem"; 
      this->helpToolStripMenuItem->Size = System::Drawing::Size(44, 20); 
      this->helpToolStripMenuItem->Text = L"&Help"; 
      // 
      // aboutToolStripMenuItem 
      // 
      this->aboutToolStripMenuItem->Name = L"aboutToolStripMenuItem"; 
      this->aboutToolStripMenuItem->Size = System::Drawing::Size(116, 22); 
      this->aboutToolStripMenuItem->Text = L"&About..."; 
      // 
      // button1 
      // 
      this->button1->Location = System::Drawing::Point(623, 476); 
      this->button1->Name = L"button1"; 
      this->button1->Size = System::Drawing::Size(75, 23); 
      this->button1->TabIndex = 2; 
      this->button1->Text = L"Close"; 
      this->button1->UseVisualStyleBackColor = true; 
      // 
      // lblQuizLogin 
      // 
      this->lblQuizLogin->AutoSize = true; 
      this->lblQuizLogin->Location = System::Drawing::Point(12, 489); 
      this->lblQuizLogin->Name = L"lblQuizLogin"; 
      this->lblQuizLogin->Size = System::Drawing::Size(70, 13); 
      this->lblQuizLogin->TabIndex = 3; 
      this->lblQuizLogin->Text = L"Not logged in"; 
      // 
      // QuizForm 
      // 
      this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); 
      this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; 
      this->ClientSize = System::Drawing::Size(710, 511); 
      this->Controls->Add(this->lblQuizLogin); 
      this->Controls->Add(this->button1); 
      this->Controls->Add(this->tabControl); 
      this->Controls->Add(this->menuStrip1); 
      this->MainMenuStrip = this->menuStrip1; 
      this->MaximizeBox = false; 
      this->MinimizeBox = false; 
      this->Name = L"QuizForm"; 
      this->StartPosition = System::Windows::Forms::FormStartPosition::CenterScreen; 
      this->Text = L"Interactive Quiz"; 
      this->Load += gcnew System::EventHandler(this, &QuizForm::QuizForm_Load); 
      this->tabControl->ResumeLayout(false); 
      this->menuStrip1->ResumeLayout(false); 
      this->menuStrip1->PerformLayout(); 
      this->ResumeLayout(false); 
      this->PerformLayout(); 

     } 
#pragma endregion 

private: System::Void QuizForm_Load(System::Object^ sender, System::EventArgs^ e) { 
      introForm^ intro = gcnew introForm; // the second introForm in this line is underlined with the mentioned error 
     } 
    }; 
} 

#endif // !__QuizForm__H__ 

你在這2個的代碼中看到的是我作爲構建拼圖,我發現整個網絡,哈哈。 :)

我的目標:能夠使用一個變量從introFormQuizForm

在此先感謝! Boris J.

+1

考慮到這一點:http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-ac-identifier – chris 2013-02-25 20:40:07

+0

扔掉大部分的代碼和嘗試重現問題。在尋求幫助之前,我就是這麼做的。 – 2013-02-25 20:41:18

+3

這不是C++。至少我看到的代碼中有10%不是。 – juanchopanza 2013-02-25 20:44:28

回答

13

當在C++中使用對象的前向聲明時,請記住一些事情。

  • 你不能分配一個不完整的類型,因爲編譯器不知道它有多大。這隻通過使用指向不完整類型的指針來解決。
  • 在編譯器看到定義之前,您不能引用不完整類型的成員。這是通過將你的接口和實現分離到頭文件和代碼文件來解決的。
  • 如果您處於使用不完整類型的情況,那麼您可能是在做錯某些事情。儘可能避免循環引用。

在問候您的評論:

當你有一個類的預先聲明,像class foo;,這就是所謂的一個不完整的類型,定義尚不存在。您可以通過指針間接引用它,如foo *bar;,但不能在任何需要知道其內部組件的操作中使用它,例如使用它包含的函數等。您可以完全聲明類,儘管使用函數原型而不是函數。然後可以在另一個文件中定義函數。這將允許你完全定義一個循環依賴而不會造成任何事情。 例如:

On codepad with the headers inline-included.

的單個文件:

foo.h中:

#ifndef __FOO_H_INCLUDE 
    #define __FOO_H_INCLUDE 
    #ifndef __FOO_H_DEFINED 
     #define __FOO_H_DEFINED 
     class foo; 
     #include "bar.h" 
    #endif 
    class foo{ 
     bar *a; 
     int b; 
     public: 
     foo(int _b); 
     bar& getbar(); 
     int getb(); 
     void setbar(bar* _a); 
    }; 
#endif 

bar.h:

#ifndef __BAR_H_INCLUDE 
    #define __BAR_H_INCLUDE 
    #ifndef __BAR_H_DEFINED 
     #define __BAR_H_DEFINED 
     class bar; 
     #include "foo.h" 
    #endif 
    class bar{ 
     foo *a; 
     int b; 
     public: 
     bar(int _b); 
     foo& getfoo(); 
     int getb(); 
     void setfoo(foo* _a); 
    }; 
#endif 

main.cpp中:

#include<iostream> 
#include "foo.h" 
#include "bar.h" 

foo::foo(int _b){ b = _b;} 
int foo::getb(){ return b; } 
bar& foo::getbar(){ return *a; } 
void foo::setbar(bar* _a){ a = _a; } 

bar::bar(int _b){ b = _b;} 
int bar::getb(){ return b; } 
foo& bar::getfoo(){ return *a; } 
void bar::setfoo(foo* _a){ a = _a; } 



int main(){ 
    foo a(5); 
    bar b(20); 
    a.setbar(&b); 
    b.setfoo(&a); 
    std::cout << a.getbar().getfoo().getbar().getb() 
       << "\n" 
       << a.getbar().getfoo().getbar().getfoo().getb(); 
    return 0; 
} 
+0

謝謝,但我不太明白你的意思;我對這個術語還沒有那麼深入。你能告訴我我錯在哪裏,我該如何實現我所需要的?我需要從QuizForm.h中的introForm.h中訪問一個變量,但我不能,因爲introForm.h包含QuizForm.h,所以我不能簡單地在QuizForm.h中包含introForm.h。因爲這將是相互包容。建議? – 2013-02-26 00:38:09

+0

我用一個代碼示例更新了答案,以最正常的方式解決了您的問題。 – Kaslai 2013-02-26 05:02:39

+0

謝謝......我會考慮你的樣本! – 2013-02-26 10:59:10