2013-02-25 62 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

相关问题