60分求助一个简单的问题,各位高手老大们,停一停站一站,过来看一看吧!谢谢!

时间:2022-02-10 14:17:32
我有两个form,当我在form2 里面包含了form1,在form1里面包含了form2的时候,也就是说两个form彼此互相包含。这时候就出现了错误,说是type name expected 和declaration missing;下面是源程序,非常感谢!

unit1.h

//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "unit2.h"
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
private: // User declarations
        TForm2 *form2;
public: // User declarations
        __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
 
unit1.cpp


//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
        form2=new TForm2(NULL);
        form2->Show();
}
//---------------------------------------------------------------------------

unit2.h

//---------------------------------------------------------------------------

#ifndef Unit2H
#define Unit2H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "unit1.h"
//---------------------------------------------------------------------------
class TForm2 : public TForm
{
__published: // IDE-managed Components
private: // User declarations
public: // User declarations
        __fastcall TForm2(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm2 *Form2;
//---------------------------------------------------------------------------
#endif

unit2.cpp

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
        : TForm(Owner)
{
        SetActiveWindow(Form1->Handle);
}
//---------------------------------------------------------------------------
 

18 个解决方案

#1


这是一个嵌套定义,循环调用.肯定不行的.
为何要这样定义呢?你在form1中调用form2,然后在form2中激活form1,你想干么?

而且:我认为在form1中调用form2的语句不要放在构造函数,应该放在OnCreate事件中
同样在form2 中激活form1 的语句也应该放在OnCreate事件中

还有你可以这样声明:
在Unit1.cpp中和Unit2.cpp写
#include "Unit2.h"和 #include "Unit1.h"
而不要在Unit1.h中和Unit2.h中写include 语句.

这样能避免嵌套定义,循环调用

#2


最简单的解决方法就是再做一个units.h
里面包含所有的unit的头文件
#include "unit1.h"
#include "unit2.h"

在unit?.cpp里包含它就可以了,以后只要修改一个头文件就没事了。

#3


如果你的意图是动态生成窗体,可以按如下步骤做:
1.在Project选项中,将窗体2从自动创建中删除;
2.去掉TForm1 的私有成员 form2;
3.直接对Form2 (extern PACKAGE TForm2 *Form2) 对象操作.

#4


肯定不是这个原因。
#ifndef Unit1H
...

#ifndef Unit2H
...
就是为了防止嵌套定义的。

#5


请问 holyfire(因为我手快所以我抢先用了水神这个昵称) wjzhuang(程序猪) 二位
#ifndef unit1h
#define unit1h
#endif
是干什么用的?

#6


这样定义,肯定可以,验证通过:
unit1.h

//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "unit2.h"
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE-managed Components
private:    // User declarations
        class TForm2;
        TForm2 *form2;
public:        // User declarations
        __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif


#7


to Wingsun(孙春阳)
但是如果加上
unit2.h

//---------------------------------------------------------------------------

#ifndef Unit2H
#define Unit2H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "unit1.h"

世界就变得很奇妙了,哈哈,不行

#ifndef unit1h
#define unit1h
#endif
预编译
看也能看明白
第一次包含unit1.h
#ifndef unit1h   //如果没有定义unit1h,的确没有定义,条件为真
#define unit1h   //定义unit1h
#endif           //if嵌套结束

那么第二次包含unit1.h时
#ifndef unit1h   //unit1h已经定义了,条件为假
#define unit1h   //中间的都不执行
#endif          //if嵌套结束



#8


我刚刚试过,唯一的不同就是我的FORM一个是form1一个是form3
没有问题。

#9


怎么会没问题,我用看的都知道有问题
unit1.h
包含
unit2.h

unit2.h
包含
unit1.h

这一看就知道逻辑有问题。

#10


还是不行呀,照Wingsun的改完以后,又有了别的错误,是在form2=new TForm2(NULL);这句上,说cannot convert 'int' to TForm1:TForm2'
其实我的问题是这么来的,我在编译个程序,里面有两个窗口,一大一小,是通过把小窗口注册成ole拖放窗口来得到数据,然后送到大窗口里处理。这样就有了至少3个类,mainform,dropbasket和oledroptarget,我把他们放在单独的文件里面,这样就是6个文件,小窗口是通过new在大窗口里产生的,然后再在小窗口里面声明一个MyDropTarget的类用来把小窗口注册为ole拖放窗口,在MyDropTarget里面的OnDrop事件里,我需要把得到的信息传到mainform里,所以就要调用mainform里的一个函数,比如说是void __fastcall AddToList(CTask *task).
所以我就在mainform.h里包含了dropbasket.h,而由于我需要在小窗口里面控制mainform的状态,所以在dropbasket.h里面又包含了mainform.h,同时在dropbasket.h里面也包含了oledroptarget.h,在oledroptarget.h里面又包含了mainform.h,所以就造成了type name expected 和declaration missing;的错误,各位老大,版主,你们看我该怎么改?

#11


为什么互相包含不可以?DELPHI都允许嵌套包含呢,没有理由BCB不支持嵌套的。我正在测试,等30分钟以后在发帖子。

#12


我修改了一下你的代码,其实你所缺少的也许只是在:
unit1.cpp

#include "Unit1.h"
#include "unit2.h"  //这一行你没有加。
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

而已。

另外,
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
        form2=new TForm2(NULL);
        form2->Show();
}
中的NULL要改成this;

WINGSUN的方法实际上是可行的,他采用的是预声明,即在真正的类(A)定义之前,预先给要用到这个类A的类(B)声明一个空的A的定义,称为Forward Declaration,是常用手法之一。
--------------------------------------------------------------------
题外话,以后提问时,如果不是太确定,不要将问题简化得太厉害。当然,你这个帖子将问题简化后没有造成问题本质的偏离。

#13


支持,怎么可能不支持啊。我前几天才看到的文章讲这样可以。
要不,这样写
unit1.h

//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "unit2.h"
//---------------------------------------------------------------------------
class TForm2;
class TForm1 : public TForm
{
__published:    // IDE-managed Components
private:    // User declarations
        TForm2 *form2;
public:        // User declarations
        __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif


#14


我对你的MyDropTarget比较感兴趣,这几天我也在看这方面的资料(OleDrag)。不如给我看一看?

#15


谢谢各位帮忙,已经可以了,马上给分。

To TR@SOE()斑竹,在哪里能找到关于Forward Declaration的文章?

To Wingsun,我在另开一个贴子给你吧!

#16


软件工程告诉我们,要用简洁的方式。在.cpp里互相包含一点问题也没有,为什么要独出心裁。出问题也很正常了。

#17


大概没有专门讲Forward Declaration的书吧?那实际是很常见、很一般的C++技巧而已。例如:

class B;
class A:public TObject
{
...
friend Manipulate(class &B);
...
};

class B:public TObject
{
friend Manipulate(class &A);
...
};

在这里,不使用Forward Declaration是不能实现的。

#18


我认为"#inlcude "unitX" 这样的语句还是放在.cpp文件中会比较好.

在头文件中显得不清晰.

容易造成上面的问题.

而在.cpp文件中声明的话,完全可以避免问题,程序看起来也很清楚.为何不用这种方法呢?

#1


这是一个嵌套定义,循环调用.肯定不行的.
为何要这样定义呢?你在form1中调用form2,然后在form2中激活form1,你想干么?

而且:我认为在form1中调用form2的语句不要放在构造函数,应该放在OnCreate事件中
同样在form2 中激活form1 的语句也应该放在OnCreate事件中

还有你可以这样声明:
在Unit1.cpp中和Unit2.cpp写
#include "Unit2.h"和 #include "Unit1.h"
而不要在Unit1.h中和Unit2.h中写include 语句.

这样能避免嵌套定义,循环调用

#2


最简单的解决方法就是再做一个units.h
里面包含所有的unit的头文件
#include "unit1.h"
#include "unit2.h"

在unit?.cpp里包含它就可以了,以后只要修改一个头文件就没事了。

#3


如果你的意图是动态生成窗体,可以按如下步骤做:
1.在Project选项中,将窗体2从自动创建中删除;
2.去掉TForm1 的私有成员 form2;
3.直接对Form2 (extern PACKAGE TForm2 *Form2) 对象操作.

#4


肯定不是这个原因。
#ifndef Unit1H
...

#ifndef Unit2H
...
就是为了防止嵌套定义的。

#5


请问 holyfire(因为我手快所以我抢先用了水神这个昵称) wjzhuang(程序猪) 二位
#ifndef unit1h
#define unit1h
#endif
是干什么用的?

#6


这样定义,肯定可以,验证通过:
unit1.h

//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "unit2.h"
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:    // IDE-managed Components
private:    // User declarations
        class TForm2;
        TForm2 *form2;
public:        // User declarations
        __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif


#7


to Wingsun(孙春阳)
但是如果加上
unit2.h

//---------------------------------------------------------------------------

#ifndef Unit2H
#define Unit2H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "unit1.h"

世界就变得很奇妙了,哈哈,不行

#ifndef unit1h
#define unit1h
#endif
预编译
看也能看明白
第一次包含unit1.h
#ifndef unit1h   //如果没有定义unit1h,的确没有定义,条件为真
#define unit1h   //定义unit1h
#endif           //if嵌套结束

那么第二次包含unit1.h时
#ifndef unit1h   //unit1h已经定义了,条件为假
#define unit1h   //中间的都不执行
#endif          //if嵌套结束



#8


我刚刚试过,唯一的不同就是我的FORM一个是form1一个是form3
没有问题。

#9


怎么会没问题,我用看的都知道有问题
unit1.h
包含
unit2.h

unit2.h
包含
unit1.h

这一看就知道逻辑有问题。

#10


还是不行呀,照Wingsun的改完以后,又有了别的错误,是在form2=new TForm2(NULL);这句上,说cannot convert 'int' to TForm1:TForm2'
其实我的问题是这么来的,我在编译个程序,里面有两个窗口,一大一小,是通过把小窗口注册成ole拖放窗口来得到数据,然后送到大窗口里处理。这样就有了至少3个类,mainform,dropbasket和oledroptarget,我把他们放在单独的文件里面,这样就是6个文件,小窗口是通过new在大窗口里产生的,然后再在小窗口里面声明一个MyDropTarget的类用来把小窗口注册为ole拖放窗口,在MyDropTarget里面的OnDrop事件里,我需要把得到的信息传到mainform里,所以就要调用mainform里的一个函数,比如说是void __fastcall AddToList(CTask *task).
所以我就在mainform.h里包含了dropbasket.h,而由于我需要在小窗口里面控制mainform的状态,所以在dropbasket.h里面又包含了mainform.h,同时在dropbasket.h里面也包含了oledroptarget.h,在oledroptarget.h里面又包含了mainform.h,所以就造成了type name expected 和declaration missing;的错误,各位老大,版主,你们看我该怎么改?

#11


为什么互相包含不可以?DELPHI都允许嵌套包含呢,没有理由BCB不支持嵌套的。我正在测试,等30分钟以后在发帖子。

#12


我修改了一下你的代码,其实你所缺少的也许只是在:
unit1.cpp

#include "Unit1.h"
#include "unit2.h"  //这一行你没有加。
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

而已。

另外,
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
        form2=new TForm2(NULL);
        form2->Show();
}
中的NULL要改成this;

WINGSUN的方法实际上是可行的,他采用的是预声明,即在真正的类(A)定义之前,预先给要用到这个类A的类(B)声明一个空的A的定义,称为Forward Declaration,是常用手法之一。
--------------------------------------------------------------------
题外话,以后提问时,如果不是太确定,不要将问题简化得太厉害。当然,你这个帖子将问题简化后没有造成问题本质的偏离。

#13


支持,怎么可能不支持啊。我前几天才看到的文章讲这样可以。
要不,这样写
unit1.h

//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "unit2.h"
//---------------------------------------------------------------------------
class TForm2;
class TForm1 : public TForm
{
__published:    // IDE-managed Components
private:    // User declarations
        TForm2 *form2;
public:        // User declarations
        __fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif


#14


我对你的MyDropTarget比较感兴趣,这几天我也在看这方面的资料(OleDrag)。不如给我看一看?

#15


谢谢各位帮忙,已经可以了,马上给分。

To TR@SOE()斑竹,在哪里能找到关于Forward Declaration的文章?

To Wingsun,我在另开一个贴子给你吧!

#16


软件工程告诉我们,要用简洁的方式。在.cpp里互相包含一点问题也没有,为什么要独出心裁。出问题也很正常了。

#17


大概没有专门讲Forward Declaration的书吧?那实际是很常见、很一般的C++技巧而已。例如:

class B;
class A:public TObject
{
...
friend Manipulate(class &B);
...
};

class B:public TObject
{
friend Manipulate(class &A);
...
};

在这里,不使用Forward Declaration是不能实现的。

#18


我认为"#inlcude "unitX" 这样的语句还是放在.cpp文件中会比较好.

在头文件中显得不清晰.

容易造成上面的问题.

而在.cpp文件中声明的话,完全可以避免问题,程序看起来也很清楚.为何不用这种方法呢?