C ++ Cli — 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__

То, что вы видите в этих двух частях кода, — это то, что я построил как кусочки головоломки, которые я нашел по всей сети, ха-ха. 🙂

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

Заранее спасибо!
Борис Яковлевич

2

Решение

При использовании предварительных объявлений объектов в C ++ помните о нескольких вещах.

  • Вы не можете выделить неполный тип, так как компилятор еще не знает, насколько он велик. Это решается только использованием указателей на неполные типы.
  • Вы не можете ссылаться на члены неполного типа, пока его определение не будет замечено компилятором. Это решается разделением вашего интерфейса и реализации на файлы заголовка и кода.
  • Если вы находитесь в ситуации, когда вы иметь Если вы используете неполный тип, вы, вероятно, делаете что-то не так. Старайтесь избегать круговых ссылок, где это возможно.

Что касается вашего комментария:

Когда у вас есть предварительное объявление класса, как class foo;, он называется неполным типом, так как определение еще не существует. Вы можете ссылаться на него косвенно с помощью указателей, например, foo *bar;, но вы не можете использовать его в любых операциях, требующих знания его внутренних компонентов, таких как разыменование его, использование содержащихся в нем функций и т. д. Вы можете сделать полное объявление класса, хотя вместо функций используются прототипы функций. Затем вы можете определить функции в другом файле. Это позволит вам полностью определить круговую зависимость, не делая ничего взорванного.
Например:

На кодовой панели со встроенными заголовками.

Отдельные файлы:

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;
}
13

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]