Lippman的《深度探索C++对象模型》一书中,有一章专门提到了C++中关键词所带来的差异。其中一个主要的问题就是:struct与class的区别。
网上看了一些其他文章,写的简直扯淡。各种这个区别那个区别。
其实一句话:除了默认访问权限,啥区别都没有,任何地方都能互换,但出于兼容性考虑,不推荐用将struct作为类语义使用。
struct与class对于Parser而言,都用同一个符号“AGGR”表示。因此在功能上和语法上表现出的行为是一样的。用到struct和class的地方,可以用struct与class相互替换而不影响程序的行为:struct可以和class相互混合继承,模板中可以用template<class T>也可以用template<structT>,甚至前面声明用struct后面定义改用class也没事,如果有虚成员,布局里也都会偷偷塞进来一个vptr,反正你能想到的任何地方都是这样。两个关键字一体两面,简直就是The Prestige,看我百变小樱变变变,感觉貌似很爽的样子。但是事实上,语法上成立的东西不一定在实践中也好用。
当然必须指出的是,语法上,struct与class也并不真是完全等价的:这体现在两点上:
-
成员的默认访问权限:struct是public,class是private。
-
默认的继承权限:struct是public,class是private。
不过这一点在编程实践上用处不是很大,正常人应该都会为所有成员显式声明访问控制说明符,不差那几下按键。
首先是标准的建议,能用class就不要用struct,因为struct是C关键字。在C++中使用struct是一种Deprecate的行为,不被推荐。主要是出于和C语言的兼容性考虑:struct应当单纯地用于数据成员的聚合。打包传参这种功能struct是很合适的。但往里面放成员函数就不合适了。
另一点是从语义上出发的:在C#中,struct被理解为值类型,分配于栈上。而class则是引用类型,分配在堆上。我认为这种划分是很妥当的。struct本身就是一个legacy,身上深深地烙上了洪荒年代程序员用过程摆弄包裹在结构体中二进制位朴素思想的影子。而class则显得富有时代气息,代表了一种面向对象的思想,尤其是由C#\Java转向C++的,肯定很能理解。既然考虑向下兼容C,不妨也再考虑一下向上兼容C#/Java。尤其是java压根都没有struct关键字....。事实上,struct和class的这种隐含意义倒是可以用于提升程序可读性的实践上,如果某个类型是值语义,采用struct声明;引用类型,则采用class声明。当然,不过是语法糖罢了,最佳实践还是像标准说的那样做:只用class。