C++头文件和类实例的大小之间的关系
2008-08-22 14:25
267 查看
在C++中为类编写头文件的时候,总要#include一大堆头文件。其实其中的大部分都是不需要的。
C++编辑器需要做的事情其实很简单1:扫描符号2:确定对象的大小。
为了确定这两件事情并不一定需要#include你用到的其他类的头文件。而只需要一个类型申明而已.
1.使用到类型的引用。首先我们知道对象的引用不是对象本身而是类似指针一样的东西。所以任何类型的对象的引用所占有的空间都是相同的。所以这里为了确定类型对象的大小,并不需要#include所使用到的类型的定义。
举例如下:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#ifndef SAMPLE_H_
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#define SAMPLE_H_
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
class Sample
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Sample();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
virtual ~Sample();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private :
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
string& mSampleName;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
};
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#endif /*SAMPLE_H_*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
这段代码会产生一个编译错误.具体的原因就是 找不到string这个类型。那么如何解决呢?我以前一般都是#include <string> using namespace std;其实这里不需要 因为mSampleName是一个string的引用而已.
只需要前向声明一下她是一个类型就可以了。
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#ifndef SAMPLE_H_
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#define SAMPLE_H_
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
class string;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
class Sample
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Sample();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
virtual ~Sample();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private :
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
string& mSampleName;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
};
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#endif /*SAMPLE_H_*/注意新添加的那一行,这样就可以了。
2.使用类型的指针
和上面的例子一样,指针的大小总是可以确定的。所以也不需要#include头文件。只需要前向声明就可以了。
3.在成员函数的参数中使用的类型
无论类型是什么都只需要使用前向声明,因为成员函数几乎是不占对象的大小的。
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#ifndef SAMPLE_H_
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#define SAMPLE_H_
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
class string;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
class IEnvelope;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
class Sample
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Sample();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
virtual ~Sample();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
IEnvelope GetEnvelope();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
bool QueryEnvelope(IEnvelope& pEnv);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private :
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
string& mSampleName;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
};
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#endif /*SAMPLE_H_*/在写这段代码的时候我的project中根本就没有IEnvelope这个类型。所以其实根本没有IEnvelope.h可以#include。但是使用前向声明就可以让代码编译过去。这是因为成员函数不占用对象大小的原因。
总之在头文件里面如果你认为即使不能确定所使用到的某个类型的大小还是可以确定当前类型的对象的大小的时候就可以不用#include所使用到的类型的头文件。只需要前向声明一下就可以了。前向声明的作用在于告诉编译器这个一个在别的地方定义的类型。这样C++编译器就能生成正确的符号表了。
C++编辑器需要做的事情其实很简单1:扫描符号2:确定对象的大小。
为了确定这两件事情并不一定需要#include你用到的其他类的头文件。而只需要一个类型申明而已.
1.使用到类型的引用。首先我们知道对象的引用不是对象本身而是类似指针一样的东西。所以任何类型的对象的引用所占有的空间都是相同的。所以这里为了确定类型对象的大小,并不需要#include所使用到的类型的定义。
举例如下:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#ifndef SAMPLE_H_
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#define SAMPLE_H_
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
class Sample
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Sample();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
virtual ~Sample();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private :
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
string& mSampleName;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
};
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#endif /*SAMPLE_H_*/
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
这段代码会产生一个编译错误.具体的原因就是 找不到string这个类型。那么如何解决呢?我以前一般都是#include <string> using namespace std;其实这里不需要 因为mSampleName是一个string的引用而已.
只需要前向声明一下她是一个类型就可以了。
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#ifndef SAMPLE_H_
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#define SAMPLE_H_
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
class string;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
class Sample
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Sample();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
virtual ~Sample();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private :
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
string& mSampleName;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
};
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#endif /*SAMPLE_H_*/注意新添加的那一行,这样就可以了。
2.使用类型的指针
和上面的例子一样,指针的大小总是可以确定的。所以也不需要#include头文件。只需要前向声明就可以了。
3.在成员函数的参数中使用的类型
无论类型是什么都只需要使用前向声明,因为成员函数几乎是不占对象的大小的。
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#ifndef SAMPLE_H_
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#define SAMPLE_H_
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
class string;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
class IEnvelope;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
class Sample
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif)
...{
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
Sample();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
virtual ~Sample();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
public:
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
IEnvelope GetEnvelope();
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
bool QueryEnvelope(IEnvelope& pEnv);
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
private :
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
string& mSampleName;
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif)
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif)
};
![](http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif)
#endif /*SAMPLE_H_*/在写这段代码的时候我的project中根本就没有IEnvelope这个类型。所以其实根本没有IEnvelope.h可以#include。但是使用前向声明就可以让代码编译过去。这是因为成员函数不占用对象大小的原因。
总之在头文件里面如果你认为即使不能确定所使用到的某个类型的大小还是可以确定当前类型的对象的大小的时候就可以不用#include所使用到的类型的头文件。只需要前向声明一下就可以了。前向声明的作用在于告诉编译器这个一个在别的地方定义的类型。这样C++编译器就能生成正确的符号表了。
相关文章推荐
- C++中头文件和类的实例的大小之间的关系
- C++中头文件、源文件之间的区别与联系
- C Runtime Library、C++ Runtime Library、Windows API 和 C++标准四者之间的关系
- Oracle 数据库 实例之间的关系及一些名词解释(上)
- 分享:C++中头文件、源文件之间的区别与联系
- oracle数据库_实例_用户_表空间之间的关系
- POSIX中有亲缘关系的进程之间的匿名内存共享的简单实例
- C++多态 重写 重载 隐藏之间的关系
- java应用程序和虚拟机实例之间的关系
- c++空类实例大小不是0原因
- 创建Oracle数据库、数据库名与实例名与SID之间的关系(图文详解)
- STL和c++、MFC之间是什么关系?
- Oracle - 数据库的实例、表空间、用户、表之间关系
- C++ - const常量与指针和引用之间的关系
- h头文件 .lib库文件 .dll动态库文件之间的关系
- 重载和多态之间的关系?!(C++初学者)
- c++空类实例大小不是0原因
- 转:c++空类实例大小不是0原因
- 实例解析C++/CLI程序进程之间的通讯
- 统计思维(实例5)——变量之间的关系