2013-02-25 3 views
1

У меня есть два класса (или, еще лучше, заголовочные файлы), которые являются частью моей программы на C++, и я просто не могу заставить все это работать! Они в основном нуждаются в данных друг друга, чтобы нормально функционировать, как часть моего приложения.Ошибка C++ Forward и ошибка «Незавершенный тип недопустима»

Не мучите себя, читая мясо этого кода; Мне просто нужно отправить объявление об объявлении и взаимное включение проблема решена, поэтому взгляните только на те части кода, которые имеют значение для этой проблемы.

Ошибка возникает во втором фрагменте кода, в самом конце (мне пришлось отрубить огромный фрагмент кода из первого фрагмента, поэтому я мог бы поставить вопрос, я думаю, это не имеет отношения к моей проблеме).

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-х кусков кода то, что я построил, как кусочки головоломки, которые я нашел по всей сети, ха-ха. :)

Моя цель:, чтобы иметь возможность использовать переменную из introForm внутри QuizForm.

Заранее благодарен! Boris J.

+1

Примите это к сведению: http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-ac-identifier – chris

+0

Отбросьте большую часть кода и попытайтесь воспроизвести проблему. Это то, что я сделал бы, прежде чем просить о помощи. –

+3

Это не C++. По крайней мере, 10% кода, на который я смотрел, - нет. – juanchopanza

ответ

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

Спасибо, но я не совсем понимаю, что вы сказали; Я еще не настолько «глубоко» в этой терминологии. Не могли бы вы рассказать мне, где я ошибаюсь, и как я могу достичь того, что мне нужно? Мне нужно получить доступ к переменной из introForm.h изнутри QuizForm.h, но я не могу, потому что introForm.h включает QuizForm.h, поэтому я не могу просто включить introForm.h в QuizForm.h. потому что это будет взаимное включение. Предложения? –

+0

Я обновил ответ с помощью примера кода, который решает вашу проблему самым разумным способом. – Kaslai

+0

Спасибо ... Я отвечу на ваш образец! –