分享好友 编程语言首页 频道列表

VC++开发中完美解决头文件相互包含问题的方法解析

VC/MFC  2015-07-21 09:240

所谓超前引用是指一个类型在定义之前就被用来定义变量和声明函数。

一般情况下,C/C++要求所有的类型必须在使用前被定义,但是在一些特殊情况下,这种要求无法满足,例如,在类CMyView中保留了一个非模式对话框对象指针,该对象用于显示/修改一些信息。为了实现对话框"应用"按钮,把对话框做的修改立刻更新到view界面上,为此,需要在对话框类中需要保存view类的指针,这样定义关系就变成如下的代码:

复制代码 代码如下:

   #ifndef __MYVIEW_H__
   #define __MYVIEW_H__
   //这是view类的头函数
   #include "MyDialog.h"
   class CMyView::public CView
   {
   protected:
       CMyDialog * pDlg;
       //这里是其他定义
   };
   #endif

   #ifndef __MYDIALOG_H__
   #define __MYDIALOG_H__
   //这是对话框类的定义
   #include "MyView.h"
   class CMyDialog::public CDialog
   {
       protected:
CMyView * pView;
//其他定义
   };
   #endif

从编译器角度看,编译MyDialog.CPP时,系统首先定义宏__MYDIALOG_H__,然后包含MyView.h,MyView.h中的#include "MyDialog.h"由于__MYDIALOG_H__已经定义,所以不再起作用。在CMyView类的声明中,CMyDialog* pDlg ;就会让编译器产生"CMyDialog"类型没有定义之类的错误,编译MyView.CPP文件出现的错误可以类似得到。   

一般的情况,类A和类B需要彼此互相引用,这样必然有一个类会先被定义,而另外一个类后被定义,这样在先被定义的类引用后被定义的类的时候,就导致了所谓的超前引用。

超前引用导致的错误有以下几种处理办法:

1) 使用类声明
在超前引用一个类之前,首先用一个特殊的语句说明该标识符是一个类名,即将被超前引用。其使用方法是:
a)  用class ClassB;声明即将超前引用的类名
b)  定义class ClassA
c)  定义class ClassB;
d)  编制两个类的实现代码。
上述方法适用于所有代码在同一个文件中,一般情况下,ClassA和ClassB分别有自己的头文件和cpp文件,这种

方法需要演变成:
a) 分别定义ClassA和ClassB,并在cpp文件中实现之
b) 在两个头文件的开头分别用class ClassB;和class ClassA;声明对方
c) 在两个cpp文件中分别包含另外一个类的头文件
NOTE:这种方法切记不可使用类名来定义变量和函数的变量参数,只可用来定义引用或者指针。    

2) 使用全局变量
由于全局变量可以避免超前引用,不用赘述。我的习惯是,把类对象的extern语句加在该类头文件的最后,大家喜欢怎样写那都没有什么大问题,关键是保证不要在头文件中胡乱包含。

3) 使用基类指针。
这种方法是在引用超前引用类的地方一律用基类指针。而一般情况下,两个互相引用的类并不涉及其基类,因此不会造成超前引用。以开始的例子说:在CMyDialog类中用CView*代替CMyView*,在CMyView类中用CDialog*代替CMyDialog*,这样必然不会造成超前引用。

说明:本文中,为了叙述方便,把class AClass;语句成为类AClass的声明,把class AClass开始的对AClass的类成员变量、成员函数原型等的说明称为类的定义,而把在CPP中的部分称为类的定义。如果大家对这三个词有不同的理解,请按照自己的本意把这三个词换成相应的词来理解。

ps:我是用第一种方法解决问题的。

查看更多关于【VC/MFC】的文章

展开全文
相关推荐
反对 0
举报 0
评论 0
图文资讯
热门推荐
优选好物
更多热点专题
更多推荐文章
Delphi VCL 在TRichEdit控件中设置WordWrap属性后无法自动换行的问题
最近在使用RAD XE7时,在WIN10上开发一个类似记事本的工具,使用的是TRichEdit控件,在实现自动换行功能时,发现设置WordWrap后无法自动换行,经过检查发现和滚动条ScrollBars属性有关系,只要设置水平滚动条( RichEdit1.ScrollBars := TScrollStyle.ssBoth

0评论2023-02-09972

VC,BCB,C#,Delphi,Java的委托方案 vcbcbcbcb
委托(delegate)有委托接收方和委托发出方两个实例。委托接收方需要有一个函数实现,然后“拜托”别人调用。委托发出方需要有一个“服务员”接受委托接收方的“委托”请求,并记录调用入口,在非面向对象的时候用的是函数指针,现在面向对象,需要保存this后调

0评论2023-02-09911

VC调用Delphi制作的动态链接库如何互相传递字符串
1、VC to DelphiDelphi源程序:library ExportChartData; uses   SysUtils,   Classes; {$R *.res} const   DLL_VER      : Word = $0001; function GetVer: Word; begin   Result := DLL_VER; end; procedure SayHello(a

0评论2023-02-09695

(转) Lua使用心得一 LUA和VC整合
这几天研究了一下lua,主要关注的是lua和vc之间的整合,把代码都写好放在VC宿主程序里,然后在lua里调用宿主程序的这些代码(或者叫接口、组件,随便你怎么叫),希望能用脚本来控制主程序的行为。这实际上也是一种把业务分离,用脚本控制的架构,可能有些人

0评论2023-02-09498

用VC编译lua源码,生成lua语言的解释器和编译器
用VC编译lua源码,生成lua语言的解释器和编译器1.去网址下载源码 http://www.lua.org/download.html 2.装一个VC++,我用的是VC6.0 3.接下来我们开始编译源码,我们需要编译:一个静态库一个动态库一个lua语言解释器一个lua编译器建立一个工静态库工程打开VC--

0评论2023-02-09935

vc++ & matlab 换行符号
在C/C++语言中,可能我们要书写的一个字符串太长了,放在一行上影响代码的可读性。这时我们就需要多行书写了。字符串多行书写有两种规则:在字符串换行处加一个反斜杠’\’,下一行前不能有空格或者Tab键;使用双引号。 程序示例:/* *  Introduction: *

0评论2023-02-09800

vc与matlab接口用com(二) vc调用matlab函数
首先在Matlab编辑器里编辑m函数文件:启动matlab-File-New-M-file 函数内容如图1:该函数无输入输出参数,文件保存为huatu.m。function huatu()x=-10:0.1:10;y=sin(x);plot(x,y);在matlab下建立COM组件,步骤如下: 1、在matlab command window 输入如下命令

0评论2023-02-09654

【AMAD】betamax -- 一个ruby-VCR的模仿品,只支持requests
简介动机作用用法个人评分简介betamax1会记录你的HTTP操作,可以让你在测试的时候不必重复进行真实的请求。动机如果你的代码需要和外部资源一起运作,那么测试这段代码的方法就叫做集成测试。但是,其实你并没有办法确保外部资源总是如你所愿,因为它并不在你

0评论2023-02-09399

Ruby中文乱码问题 springmvc中文乱码
中文乱码问题解决方法为只要在文件开头加入 # -*- coding: UTF-8 -*-(EMAC写法) 或者 #coding=utf-8 就行了。源代码文件中,若包含中文编码,则需要注意两点:1. 必须在首行添加 # -*- coding: UTF-8 -*-,告诉解释器使用utf-8来解析源码。2. 必须设置编

0评论2023-02-09738

Objective-C(十七、KVC键值编码及实例说明)——iOS开发基础
结合之前的学习笔记以及參考《Objective-C编程全解(第三版)》,对Objective-C知识点进行梳理总结。知识点一直在变,仅仅是作为參考,以苹果官方文档为准~十七、键值编码 KVC关于KVC的知识点将通过下列样例来展开说明:Person.h文件。Person类拥有name和age两

0评论2023-02-09697

Objective-C KVC机制
Objective-C KVC机制http://blog.csdn.net/omegayy/article/details/7381301全部推翻重写一个版本,这是我在公司内做技术分享的文档总结,对结构、条理做了更清晰的调整。 1.    基本概念MODEL主要是英文文档里面经常出现的一些概念,讲解一下,方便英文

0评论2023-02-09690

iOS编程——Objective-C KVO/KVC机制[转]
这两天在看和这个相关的的内容,全部推翻重写一个版本,这是公司内做技术分享的文档总结,对结构、条理做了更清晰的调整。先找了段代码,理解下,网上看到最多的一段的关于KVC的代码先上代码 1.     1 .Person类 2.     @implementation Person

0评论2023-02-09644

VB调用VC dll的返回方式
第一种类型:数值传递注意:在VB中,默认变量传递方式为ByRef为地址,而传递值就是用ByVal,还要注意在C++中,int类型的变量是32位的,在VB中要用long型变量来配合。VC++部分:[cpp] view plaincopy extern "C" _declspec(dllexport) int __stdcall Te

0评论2023-02-09609

PHP版本VC6与VC9/VC11/VC14、Thread Safe与None-Thread Safe等的区别
       最近正好在弄一个PHP的程序,在这之前一直没有怎么以接触,发现对PHP版本知识了解不是很清楚,自己看了不少类似的文章,还是感觉不够明确和全面,       网上的结论又都是模棱两可,在此,给出最完整甚至武断的解释。(内面部分内容是摘自其它

0评论2023-02-09684

asp.net MVC 导出查询结果到Excel
首先在View视图中有一表单form,导出按钮input class="btn export" type="button" value="导出" /,在js写入点击导出按钮的代码,如下:$(".export").click(function () {window.location.href = "/Statis/ExportExecel?data=" + $("form").serial

0评论2023-02-09334

更多推荐