7

我有两个类(或者更好的是,头文件)是我的 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__

测验表格.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 段代码中看到的是我在网上找到的拼图,哈哈。:)

我的目标:能够在 QuizForm 中使用来自introForm变量

提前致谢!鲍里斯·J。

4

1 回答 1

28

When using forward declarations of objects in C++, keep a few things in mind.

  • You cannot allocate an incomplete type, as the compiler doesn't know how big it is yet. This is solved by only using pointers to incomplete types.
  • You cannot reference the members of an incomplete type before it's definition is seen by the compiler. This is solved by separating your interface and implementation in to header and code files.
  • If you are in a situation where you have to use an incomplete type, you're probably doing something wrong. Try to avoid circular references wherever possible.

In regards to your comment:

When you have a forward declaration of a class, like class foo;, it's called an incomplete type, as the definition doesn't exist yet. You can refer to it indirectly via pointers, like foo *bar;, but you can't use it in any operations that require knowledge of its internals, such as dereferencing it, using functions that it contains, etc. You can make a full declaration of a class, though using function prototypes instead of functions. You can then define the functions in another file. This will allow you to completely define a circular dependency without making anything blow up. For example:

On codepad with the headers inline-included.

The individual files:

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;
}
于 2013-02-25T20:43:40.770 回答