不允许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__
你在这两段代码中看到的是我在网上找到的拼图拼图,哈哈。:)
我的目标:能够在QuizForm内部使用IntroForm中的变量。
提前谢谢! 鲍里斯・J
解决方案
在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()
<< "
"
<< a.getbar().getfoo().getbar().getfoo().getb();
return 0;
}
相关文章