面试中偶有考官问道“class和struct有什么区别?”。回答大多千篇一律:嗯,struct中默认的存取权限是public,而class中则是private。其实这个回答并不完整。
为什么C++中会存在两个如此相似的关键字?其实struct的存在仅仅是为了保证C++对C的兼容性罢了。如此说来,既然保留了struct,而struct和class起到的作用又是一样的,为什么要引入class关键字呢?从语法上来说这是没有必要的,只是因为class这个单词的意思能更好地贴合类这种具有封装性的数据结构的实质罢了。不过随着template的引入,class和struct关键字就有了明显的不同了。
首先,我们从struct关键字在C和C++中的区别说开去。在C的编译器中,代码
struct label { /*stuff*/ }; |
只是定义了一个结构体标签label。要想在代码中产生这个结构体的具体实现t,必须采用
struct label t; |
的形式,而不能使用如下语句
label t; |
这就是为什么在C程序中常常用typedef来定义一个struct的原因了。但是上面的语句在C++的编译器中都是可行的:换而言之,C++中的struct关键字能定义一个结构体,而C中的struct关键字只能定义一个结构体的标签。
接下来让我们抛开C,在C++中探讨class和struct关键字的不同。一个很明显的区别上面已经说过了:struct中默认的存取权限是public,而class中则是private。但是这并非全部。具体的区别如下:
1. struct中默认的存取权限是public,而class中则是private;
2. 当用struct关键字构建的类成为父类时,默认的继承权限为public;而当用class关键字构建的类成为父类时,默认的继承权限是private;
3. 在模板template的<>中的类型定义仅仅支持class和typename,并不支持struct。 《Inside the C++ Object Model》中的例程如下:
template <struct type> struct test { //... }; //以上编译器会报错,正确的语法如下: template <class type> struct test { //... }; |
为什么template不支持struct?前面说了,C++中保留struct仅仅是为了与C的兼容性的话,而模板设计的初衷就没有想过与C兼容,所以抛弃struct关键字也是很自然的事情了。
4. 内存布局的不一致。在C语言的时代,一些程序员常常将单一元素的数组放到一个struct的尾部,于是每个struct object就可以拥有可变大小的数组了,代码如下:
#include <cstdio> #include <cstdlib> #include <cstring> struct mumble { /*stuff*/ char pc[1]; }; int main() { char s[] = "I'm a struct tip!"; struct mumble *pmumble = (struct mumble*)malloc(sizeof(struct mumble)+strlen(s)); strcpy(pmumble->pc,s); printf("%s",pmumble->pc); printf("%d",sizeof(pmumble->pc)); return 0; } |
看,很精巧的实现吧。不过到了C++中,这可不一定对了。在C++中凡是处于同一个access section中的数据,一定会保证其中的数据以声明的次序出现在内存中;但是多个access section的数据在内存中的出现次序就不一定了。而在引入了继承、虚函数后,这个问题就会更为复杂了。一定想在C++的类中实现这种技巧?没问题,把继承、虚函数和多个access section都弃用吧。