刚开始学C++,陷入在语法的迷惑世界里,主要是不明白为什么这么设计。后来,C++出了很多新的标准,越来越读不懂新的标准,同样,不知道为什么会有这样的标准出现,目的是什么。之前听到一个消息,大概是,写effective系列的作者,表示不会再写新书了,因为他自认为无法理解新的标准了,也说明了新标准的复杂。和C++相比,C语言更容易一些,那是太简单了。只有98年和2011年的两个标准。
随着学习和工作的深入,后来发现学习路线可能是不对的,前面一直在C++的表层游荡,没有深入到核心的部分,但什么是C++核心的部分呢?我也不能给出答案,后来看了侯捷老师翻译的《深度探索C++对象模型》这本书,是《C++ prime》作者李普曼的另一本书。这本书最早出版于1996年,当然不会写C++11标准里面的东西。读了这本书的前几章后,似乎有点嗅到C++的核心了,就是对象模型,函数成员是对数据成员操作,这和其他编程语言是相通的,就是代码对数据操作、计算等,C语言更能体现,操作内存等等,而C++也是编程语言,必然也是这样的一个“套路”,就是代码对内存进行操作,C++就是函数成员对数据成员操作,所有的规则和语法都是围绕这一点,比如const函数成员,限制函数成员不能写数据成员。意识到这一点后,渐渐明白,如果理解了C++中的类在内存中的布局,就是对象内存模型,再去学习函数成员如何操作数据成员,以及操作数据成员的规则,应该就比较容易理解了。比如构造函数,拷贝构造函数,赋值操作运算符,析构函数,这些特殊的函数成员,都是围绕“函数成员操作数据成员”的主体,都是代码操作数据,代码操作内存。
和C++标准的建立者相比,我们也可以想象如何去在内存中,去存放C++的类,函数成员和数据成员如何存放,假设我们不知道C++是怎么存放这些内容的,然后再去对照现在的C++标准,会发现现在的C++标准可能是最好的解决方案,也许有更好的解决方案,对象模型。
类中的数据成员,该如何在内存中存放呢?很明显是符合先来后到,先声明的数据成员放在内存的低地址,这是一条很显然的规则,同时也是C++中重要的一个点,比如构造顺序,构造函数的初始化列表顺序,析构的反向顺序,再加上对齐和虚表指针,对象模型就齐了。面向对象的程序设计不可能离开计算机的体系结构,它也是一种编程语言嘛,建立在计算机体系结构之上的。“无非”是代码操作数据,代码操作内存,再联想算法+数据结构,也是代码操作内存,代码对应算法,内存对应数据结构。
当然,慢慢看到了C++的核心部分时,当然我认为是类的对象模型了,一些细节也是要注意的,比如语法上的,性能优化上的,不同编译器在不同条件下的处理方式,在不了解对象模型之前,是从上往下理解,而了解和熟悉了对象模型后,是从下往上理解,这样的体验当然是不同的:前者是探索,而后者是验证,后者更像“名开天眼”,有了这双天眼(当然是夸张的说法了),用天眼去看上面所说的细节,更容易学习和理解。
理论之后,还需大量实践。实践中遇到的问题可能由于环境问题,似乎与理论不符,但其实是不可能的。这就如,规律不以人的意志为转移,一切以时间、地点和条件为转移的。当然这个规律是计算机科学的规律。在有理论指导的情况下,定位问题是比较容易的。仅仅有理论是不够的,经验也是必要的,但经验有时候也可能有负面影响,经验需要区别,因此,在看到别人的解决方案时,不一定适合当前遇到的问题,判断是很重要的。这在其他方面也是适用的。
|