详解C++ 类的前置声明的使用
来源:互联网 发布:算法帝国 编辑:程序博客网 时间:2024/05/21 17:58
刚开始学习c++
的人都会遇到这样的问题:
定义一个类 class A
,这个类里面使用了类B
的对象b
,然后定义了一个类B
,里面也包含了一个类A
的对象a
,就成了这样:
//a.h #include "b.h" class A { .... private: B b; }; //另一个头文件 b.h #include "a.h" class B { .... private: A a; };
一编译,就出现了一个互包含的问题了,这时就有人跳出来说,这个问题的解决办法可以这样,在a.h
文件中声明类B
,然后使用B的指针。
//a.h //#include "b.h" class B; class A { .... private: B *b; }; //b.h #include "a.h" class B { .... private: A a; };
然后,问题就解决了。
但是,有人知道问题是为什么就被解决的吗,也就是说,加了个前置声明为什么就解决了这样的问题。下面,让我来探讨一下这个前置声明。
类的前置声明是有许多的好处的。我们使用前置声明的一个好处是,从上面看到,当我们在类A
使用类B
的前置声明时,我们修改类B
时,只需要重新编译类B
,而不需要重新编译a.h
的(当然,在真正使用类B
时,必须包含b.h
)。
另外一个好处是减小类A
的大小,上面的代码没有体现,那么我们来看下:
//a.h class B; class A { .... private: B *b; .... }; //b.h class B { .... private: int a; int b; int c; };
我们看上面的代码,类B
的大小是12(在32位机子上)。
如果我们在类A
中包含的是B
的对象,那么类A
的大小就是12(假设没有其它成员变量和虚函数)。如果包含的是类B
的指针*b
变量,那么类A
的大小就是4,所以这样是可以减少类A
的大小的,特别是对于在STL
的容器里包含的是类的对象而不是指针的时候,这个就特别有用了。
在前置声明时,我们只能使用的就是类的指针和引用(因为引用也是居于指针的实现的)。
那么,问你一个问题,为什么前置声明只能使用类型的指针和引用呢?
如果你回答到:那是因为指针是固定大小,并且可以表示任意的类型,那么可以给你80分了。为什么只有80分,因为还没有完全回答到。想要更详细的答案,我们看下下面这个类:
class A { public: A(int a):_a(a),_b(_a){} // _b is new add int get_a() const {return _a;} int get_b() const {return _b;} // new add private: int _b; // new add int _a; };
我们看下上面定义的这个类A
,其中_b
变量和get_b()
函数是新增加进这个类的。
那么我问你,在增加进_b
变量和get_b()
成员函数后这个类发生了什么改变,思考一下再回答。
好了,我们来列举这些改变:
- 增加了
_b
变量和get_b()
成员函数; - 这个类的大小改变了,原来是4,现在是8。
- 成员
_a
的偏移地址改变了,原来相对于类的偏移是0,现在是4了。
上面的改变都是我们显式的、看得到的改变。还有一个隐藏的改变,想想是什么。。。
这个隐藏的改变是类A
的默认构造函数和默认拷贝构造函数发生了改变。
由上面的改变可以看到,任何调用类A
的成员变量或成员函数的行为都需要改变,因此,我们的a.h
需要重新编译。
如果我们的b.h
是这样的:
//b.h #include "a.h" class B { ... private: A a; };
那么我们的b.h
也需要重新编译。
如果是这样的:
//b.h class A; class B { ... private: A *a; };
那么我们的b.h
就不需要重新编译。
像我们这样前置声明类A
:
class A;
是一种不完整的声明,只要类B
中没有执行需要了解类A
的大小或者成员的操作,则这样的不完整声明允许声明指向A
的指针和引用。
而在前一个代码中的语句
A a;
是需要了解A
的大小的,不然是不可能知道如果给类B
分配内存大小的,因此不完整的前置声明就不行,必须要包含a.h
来获得类A
的大小,同时也要重新编译类B
。
再回到前面的问题,使用前置声明只允许的声明是指针或引用的一个原因是只要*这个声明没有执行需要了解类A
的大小或者成员的操作就可以了,所以声明成指针或引用是没有执行需要了解类A
的大小或者成员的操作的。
- 类前置声明的使用
- 类前置声明的使用
- 类前置声明的使用
- 详解C++ 类的前置声明的使用
- 前置声明的使用
- 前置声明的使用
- 类的前置声明
- 类的前置声明
- C++的前置声明详解
- c++ 类的前置声明
- c++ 类的前置声明
- C++类的前置声明
- 类前置声明的问题
- 类前置声明的应用
- C++类的前置声明
- C++类的前置声明
- C++ 类的前置声明
- 模板类的前置声明
- Xpath定位练习
- MySQL中distinct和group by性能比较[转]
- Jquery实现,点击选中,点击取消选中
- Parcelable
- [cocos2d-x] --- 使用位图工具自定义字体
- 详解C++ 类的前置声明的使用
- is a detailed look
- TCL语言在Doxygen中应用的一些记录
- 安卓基础(十五)
- android中ProgressDialog
- 那些强悍的PHP一句话后门【转】
- JS 控制文本空输入文字个数相关。
- 【30秒】android模拟器获取ROOT权限!!!安卓
- leetcode 6 ZigZag Conversion