c++ 头文件包含问题-include&class
http://blog.csdn.net/jiajia4336/article/details/8996254
前向声明概念(forward declaration)
在程序中引入了类类型的B.在声明之后,定义之前,类B是一个不完全类型(incompete type),即已知B是一个类型,但不知道包含哪些成员.不完全类型只能以有限方式使用,不能定义该类型的对象,不完全类型只能用于定义指向该类型的指针及引用,或者用于声明(而不是定义)使用该类型作为形参类型或返回类型的函数.
前向声明应用场景
当你需要定义两个类或者结构,例如A和B,而这两个类需要互相引用,这时候在定义A的时候,B还没有定义,那怎么引用它呢,这时候就需要前向声明(forward declaration)了,前向声明格式如下: class B;当你在定义类A之前声明了B,那么就会在程序中引入了类类型的B,编译器知道你会在后面的某个地方定义类B,所以允许你在类A中引用类B。但是,在声明之后,定义之前,类B是一个不完全类型(incompete type),即已知B是一个类型,但不知道这个类型的一些性质(比如包含哪些成员和操作)。
前向声明的使用限制:(就拿上面声明B类说明)
1.不恩能够定义B类的对象;
2.可以用于定义只想这个类型的指针或者引用;
3.用于声明使用该类型作为形参或者返回类型的函数;
除了上面的限制,我们可以用它做些什么事情吗?
在C++中,如果要编写一个新类的头文件,一般是要#include一堆依赖的头文件,但利用前向声明和c++编译器的特性,可以减少这里的工作量。
因为c++编译器做的事情主要是:1.扫描符号;2.确定对象大小。利用这个特性,当我们编写一个新类的头文件时,就可以用前向声明,减少大量的#include,减少编译的
工作量。
例如:
1.B类用到A类,操作如下,就不需要加A.h了,减少编译工作量
1:
2://B.h
3:class A;//调用类A,前向声明
4:class
5: B
6: {
7:private:
8: A *a; //声明指针
9: };
2.在声明成员函数的形参或者返回类型时,也可以用前向声明
即使我们没有定义一个foo类,也可以用,因为成员函数不占类对象的大小,编译器可以确定对象大小,前向声明的作用在于告诉编译器这个一个在别的地方定义的类型。这样编译器就能生成正确的符号表了。
1:
2://Sample.h
3:class foo;
4:class
5: Sample
6: {
7:private:
8: foo foo_test(foo &);
9: };
在一些大的工程中,可能会包含几十个基础类,免不了之间会互相引用(不满足继承关系,而是组合关系)。也就是需要互相声明。好了,这时候会带来一些混乱。如果处理得不好,会搞得一团糟,根据我的经验,简单谈谈自已的处理办法:
编码时,我们一般会尽量避免include头文件,而是采用声明class XXX。 但有时候还是必须用Include头文件,那么,两者的划分在于什么呢?
应该是很明确的,但书上好像都少有提及。
首先:
我们要明白为什么要用声明取代头文件包含:对了,是为了避免无必要的重编译(在头文件发生变更时)。 工程较大,低速机,或基础类经常变更(不合理的设计吧),编译速度还是会在意的, 另外,更为重要的是,采用声明可降低代码(class)之间的藕合度,这也是面向对象设计的一大原则。
二:一般原则:
a.头文件中尽量少include,如果可以简单申明class clsOld;解决,那最好。减少没有必要的include;
b.实现文件中也要尽量少include,不要include没有用到的头文件。
三:那什么时候可以只是简单声明class clsOld呢?
简单的说:不需要知道clsOld的内存布局的用法都可以(静态成员除外),也就是讲如果是指针或引用方式的 都行。
比如:
clsOld * m_pOld; //指针占4个字节长
clsOld & test(clsOld * pOld) {return *pOld};
一切OK。
四:什么时候不能简单声明class clsOld,必须include呢?
不满足三的情况下:
比如:
clsOld m_Objold; //不知道占据大小,必须要通过它的具体声明来计算
原因很简单,想想你要计算sizeof(classNew),但连clsOld的size都不知道,编译器显然会无能为力。
特殊情况:
int test() { return clsOld::m_sInt;}
静态成员调用,想来应该是不需要知道内存布局的,但因为需要知道m_sInt是属于clsOld命名空间 的,如果只声明class xxx显然是不足以说明的,所以必须包含头文件。
综上所述,我有以下几点建议:
1:如果有共同相关依赖(必须include)的类,比如A,B都依赖D可以放在一起,然后直接Include "d"类的使用者只需关心与本类暴露出的相关类型,内部用到的类型不用去管(不用自已去include d)。这样 给出的class,调用者才更好用(不用去看代码查找,是不是还需要包含其它头文件)。
2:如果A类依赖D B类不依赖D,可以把它们分开两个头文件。各自Include。这样可避免当D发生变化时, 避免不必要重编译。
3:类中尽量采用指针或引用方式调用其它类,这样就可以只声明class xxx了。并且这也符合资源最优 利用,更利于使用多态。
c++ 头文件包含问题-include&class的更多相关文章
- error C2504 类的多层继承 头文件包含
error C2504:头文件包含不全 今天碰到了很烦的问题,继承一个类之后,感觉头文件都包含了,可还是出现父类未定义的问题,最后发现,子类的子类在实现时,需要在cpp文件中包含所有他的父类的定义.因 ...
- VC++中的头文件包含问题
在一些大的工程中,可能会包含几十个基础类,免不了之间会互相引用(不满足继承关系,而是组合关系).也就是需要互相声明.好了,这时候会带来一些混乱.如果处理得不好,会搞得一团糟,根据我的经验,简单谈谈自已 ...
- vc下项目的头文件包含目录以及库导入预计库目录设置
1.包含目录:include 头文件包含目录设置: project->setting->C/C++->常规: Additional include directories(附加包含目 ...
- Android.mk文件c++头文件包含问题
Eclipse 中 Android.mk文件c++头文件包含问题 jni中的目录结构如下: 编译找不到头文件 LOCAL_PATH := $(call my-dir)LOCAL_C_INCLUDES ...
- ZT 头文件包含其实是一想很烦琐的工作 第一个原则应该是,如果可以不包含头文件
当出现访问类的函数或者需要确定类大小的时候,才需要用头文件(使用其类定义) http://blog.csdn.net/clever101/article/details/4751717 看到这个 ...
- c++头文件包含 #ifndef ##pragma once
2013-04-14 17:03 (分类:计算机程序) 烦死了,这种垃圾小问题很多,你又必须要知道.......在编写c++程序时,会编写多个类或者多个cpp文件,免不了要多次使用include包含头 ...
- C/C++头文件以及避免头文件包含造成的重定义方法
C 头文件 头文件是扩展名为 .h 的文件,包含了 C 函数声明和宏定义,被多个源文件中引用共享.有两种类型的头文件:程序员编写的头文件和编译器自带的头文件. 在程序中要使用头文件,需要使用 C 预处 ...
- VS2008引入头文件包含目录和lib库目录
全局级别的引入 为VS所有项目设置包含目录和库目录,对所有项目都有效 如下图所示:工具-选项-项目和解决方案-VC++目录-包含文件:在此添加头文件目录即可 工具-选项-项目和解决方案-VC++目录- ...
- 详解keil采用C语言模块化编程时全局变量、结构体的定义、声明以及头文件包含的处理方法
一.关于全局变量的定义.声明.引用: (只要是在.h文件中定义的变量,然后在main.c中包含该.h文件,那么定义的变量就可以在main函数中作为全局变量使用) 方法1: 在某个c文件里定义全局变量后 ...
随机推荐
- javaweb servlet中使用请求转发乱码
乱码的方式有很多,这里指出一种不容易想到的 *请确保您的页面单独访问正常,经过servlet请求转发时,有PrintWriter out = response.getWriter()不正常,没有正常 ...
- 优雅地使用Windows
优雅地使用Windows 理财推荐:收益还行,安全性比余额宝高,只能自己的卡转进转出所以被盗也不怕,重要的是快速取现实时到账呢 1 现金宝 :点击进入现金宝 或者百度现金宝 2 百度理财 8.baid ...
- ionic中返回上一页
.controller('NewsCtrl', ["$scope", "$ionicHistory", "$http","$tim ...
- [转载]Eclipse.ini的相关说明
原文链接:http://www.cnblogs.com/yan5lang/archive/2011/05/24/2055867.html Eclipse的启动由$ECLIPSE_HOME/eclips ...
- Caffe学习系列(10):命令行解析
训练网络命令: sudo sh ./build/tools/caffe train --solver=examples/mnist/train_lenet.sh 用预先训练好的权重来fine-tuni ...
- BZOJ 4547: Hdu5171 小奇的集合
Sol 首先,考虑这个要怎么搞...让总和最大的方法就是选出当前集合中最大的两个数相加放入集合中就可以了,证明非常简单,当前集合的和为x,它的和只会一直往后增加,所以只需要找到最大的两个数的和加入便是 ...
- CEF3开发者系列之进程和线程
CEF3是一个多进程架构框架,如果有了解过chromium的进程架构的,那么就很容易了解CEF3的多进程了.打开CEF3源代码中发布的cefclient实例,如果打开的页面带有flash或者其他插件. ...
- CEF3开发者系列之CEF3入门
CEF全称Chromium Embedded Framework,是一个基于Google Chromium 的开源项目.Google Chromium项目主要是为Google Chrome应用开发的, ...
- zpf 获取表单等数据的用法
2015年4月12日 12:25:35 星期日 zpf框架中获取表单数据的方法 //获得get,post,url中的数据 private function setData() { $this-> ...
- Qt不同类之间信号槽连接
1.类必须继承QObject. #ifndef TESTA_H #define TESTA_H #include <QObject> class TestA : public QObjec ...