有关C++的问题~~请教

首先看下边的:在dlg1中打开dlg2时,dlg2能修改dlg1中的成员变量//dlg1.cpp#include"dlg2.h"CDlg1::OnButton1(){CD... 首先看下边的:
在 dlg1 中打开 dlg2 时,dlg2 能修改 dlg1 中的成员变量

//dlg1.cpp
#include "dlg2.h"
CDlg1::OnButton1()
{
CDlg2 dlg2;
dlg2.m_pDlg1 = this;
dlg2.DoModal();
}

//dlg2.h
class CDlg1;//添加dlg1类的声明
class CDlg2 : public CDialog
{
...
public:
CDlg1 *m_pDlg1;
}

//dlg2.cpp
#include "dlg1.h"

至此,你可以在dlg2.cpp中通过m_pDlg1操作CDlg1类中的成员变量了。

这段代码我试验了一下,能完成指定的功能,但是有一些疑问:
1.就是在dlg2.h的文件中为何非得加上class CDlg1;??我把这句去掉就会错,我的想法是dlg2已经包含了1的头文件,那么在定义dlg2时,其中又定义了dlg1的指针,那么在定义1的指针时,程序不会自己通过1的头文件找到1中对dlg1这个类的定义吗?那么这样为何还要在class CDlg1?
2.我若是将在CDlg1::OnButton1()中申明CDlg2 dlg2;的语句,放在CDlg1的类的定义处申明的话,比如放在他的public下,那么就会报错?为啥?
我知道用new的放法,所以不要再说这个了,就说一下为何放在那里会出错就行了。

谢谢了
展开
 我来答
飘雪在春季
2009-08-18 · TA获得超过259个赞
知道小有建树答主
回答量:439
采纳率:0%
帮助的人:0
展开全部
1、就是在dlg2.h的文件中为何非得加上class CDlg1;??
当然需要,在dlg2中也要加上对dlg1的引用,用class CDlg1是为避免循环重复引用。
2、道理同上。

看下面的详细解释:
一、类嵌套的疑问

C++头文件重复包含实在是一个令人头痛的问题,前一段时间在做一个简单的数据结构演示程序的时候,不只一次的遇到这种问题。假设我们有两个类A和B,分别定义在各自的有文件A.h和B.h中,但是在A中要用到B,B中也要用到A,但是这样的写法当然是错误的:
class B;

class A
{
public:
B b;
};

class B
{
public:
A a;
};
因为在A对象中要开辟一块属于B的空间,而B中又有A的空间,是一个逻辑错误,无法实现的。在这里我们只需要把其中的一个A类中的B类型成员改成指针形式就可以避免这个无限延伸的怪圈了。为什么要更改A而不是B?因为就算你在B中做了类似的动作,也仍然会编译错误,表面上这仅仅上一个先后顺序的问题。
为什么会这样呢?因为C++编译器自上而下编译源文件的时候,对每一个数据的定义,总是需要知道定义的数据的类型的大小。在预先声明语句class B;之后,编译器已经知道B是一个类,但是其中的数据却是未知的,因此B类型的大小也不知道。这样就造成了编译失败,VC++6.0下会得到如下编译错误:
error C2079: ‘b’ uses undefined class ‘B’
将A中的b更改为B指针类型之后,由于在特定的平台上,指针所占的空间是一定的(在Win32平台上是4字节),这样可以通过编译。

二、不同头文件中的类的嵌套

在实际编程中,不同的类一般是放在不同的相互独立的头文件中的,这样两个类在相互引用时又会有不一样的问题。重复编译是问题出现的根本原因。为了保证头文件仅被编译一次,在C++中常用的办法是使用条件编译命令。在头文件中我们常常会看到以下语句段(以VC++6.0自动生成的头文件为例):

#if !defined(AFX_STACK_H__1F725F28_AF9E_4BEB_8560_67813900AE6B__INCLUDED_)
#define AFX_STACK_H__1F725F28_AF9E_4BEB_8560_67813900AE6B__INCLUDED_
//很多语句……
#endif

其中首句#if !defined也经常做#ifndef,作用相同。意思是如果没有定义过这个宏,那么就定义它,然后执行直到#endif的所有语句。如果下次在与要这段代码,由于已经定衫型义了那个宏,因此重复的代码不会被再次执行。这实在是一个巧妙而高效的办法。在高版本的VC++上,还可以使用这个命令来代替以上的所有:
#pragma once
它的意思是,本文件内的代码只被使用一次。

但是不要以为使用了这种机制就全部搞定了,比如在以下的代码中:

//文件A.h中的代码
#pragma once

#include “B.h”

class A
{
public:
B* b;
};

//文件B.h中的代码
#pragma once

#include “A.h”

class B
{
public:
A* a;
};

这里两者都使用了指针成员,因此嵌套本悉塌世身不会有什么问题,在主函数前面使用#include “A.h”之后,主要编译错误如下:
error C2501: ‘A’ : missing storage-class or type specifiers
仍然是类型不能找到的错误。其实这里仍然需要前置声明。分别添加前置声睁肢明之后,可以成功编译了。代码形式如下:

//文件A.h中的代码
#pragma once

#include “B.h”

class B;

class A
{
public:
B* b;
};

//文件B.h中的代码
#pragma once

#include “A.h”

class B;

class B
{
public:
A* a;
};

这样至少可以说明,头文件包含代替不了前置声明。有的时候只能依靠前置声明来解决问题。我们还要思考一下,有了前置声明的时候头文件包含还是必要的吗?我们尝试去掉A.h和B.h中的#include行,发现没有出现新的错误。那么究竟什么时候需要前置声明,什么时候需要头文件包含呢?

三、两点原则

头文件包含其实是一想很烦琐的工作,不但我们看着累,编译器编译的时候也很累,再加上头文件中常常出现的宏定义。感觉各种宏定义的展开是非常耗时间的,远不如自定义函数来得速度。我仅就不同头文件、源文件间的句则结构问题提出两点原则,仅供参考:

第一个原则应该是,如果可以不包含头文件,那就不要包含了。这时候前置声明可以解决问题。如果使用的仅仅是一个类的指针,没有使用这个类的具体对象(非指针),也没有访问到类的具体成员,那么前置声明就可以了。因为指针这一数据类型的大小是特定的,编译器可以获知。

第二个原则应该是,尽量在CPP文件中包含头文件,而非在头文件中。假设类A的一个成员是是一个指向类B的指针,在类A的头文件中使用了类B的前置声明并便宜成功,那么在A的实现中我们需要访问B的具体成员,因此需要包含头文件,那么我们应该在类A的实现部分(CPP文件)包含类B的头文件而非声明部分(H文件)。
so爱燕姿
2009-08-17 · 超过14用户采纳过TA的回答
知道答主
回答量:59
采纳率:0%
帮助的人:0
展开全部
问题1:
dlg2.h中的声明class CDlg1是必须的,因为这声明了CDlg1是一个类的类型,不然编译器不知道CDlg1是啥?而具体CDlg1是个啥结构,则编译器通过#include才知道。祥敬这不重复。
可能我没说明白,看下面纯宴消这个例子就行:
struct student
{
int num;
char name;
(*)struct student *next;
}
注意(*)处的struct,这是必须的做知,不重复,我想说的就是这个意思。

问题2没看明白,不好意思。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式