第十二章 面向对象语言的编译
软件系统的规模越来越大,并且日趋复杂,以更有效和更透明的方法来开发这样的系统的呼声与日俱增。最终的目标是从已做好的标准构件去构造软件系统,就像现在构造硬件系统那样。模块化、模块的可重用性.模块的可扩充性和抽象性是朝向这个目标的些会试,面 面向对象话言在这些方面提供了一种新的可能性。 现在,面向对象已被看成管理复杂教件系统的一种重要风范。
12.1 面向对象语言的概念
12.1.1 对象和对象类
- 对象
- 由一组属性和操作于这组属性的过程组成
- 属性到值的映射称为对象的状态 ,过程称为方法
- 对象类
- 继承
- 基类、派生类、子类、抽象类
- 子类型规则
当某个类型的一个对象在某个输入位置被需要或作为函数的返回值时,其任何子类型的对象允许出现在这些地方。 - 类B的一个对象,若它不同时是B的某个真子类的对象,那么称该对象是B的真对象,称B是该对象的运行时类型
- 方法选择规则
如果类B继承类A并且重写了方法m,那么对类B的对象b来说, 即使它作为类A的对象使用, 也必须使用在类B中定义的方法m12.1.3 信息封装
- 大多数面向对象语言提供了一种机制,它可用来将类的特征分成私有的和公共的
- 某些面向对象语言用不同的上下文区分作用域,如“在一个类中”、“在派生类中”、“在友元类中”等等
- 由编译器来实现这些作用域规则是简单而又明显的
12.2 方法的编译
将一个C++语言的类翻译成C语言的程序段,主要工作有如下几点(由继承引出的问题暂不考虑) - 将C++语言中一个类的所有非静态属性构成一个C语言的结构类型,取类的名字作为结构类型的名字
- 类的静态属性是该类的所有对象所共有的,应当翻译成C中的全局变量,但是需要改一个名字
- C++语言中类的对象声明不加翻译就成了C语言中相应结构类型的变量声明
- 将C++语言中类的非静态方法翻译成C语言的函数,对应的方法和函数的区别有下面几点:
- 函数的名字必须在原来方法名的基础上修改
- 函数声明增加一个形参this
- 在函数体中出现的函数调用也要增加一个实参
- 在方法中对本对象的非静态属性的访问,改成对this相应域的访问。在方法中对其它对象的非静态属性的访问不必修改
- 类的静态方法在定义和调用的地方都需要改名
12.3 继承的编译方案
- 如果类B直接或间接继承类A,类B的对象可以用在几乎所有类A的对象可用的地方。
- 为了使类B的对象可以作为类A的对象使用,编译器必须能以一种有效的方式产生类B的对象的A视图。
- 由于类A的虚方法可以在类B中被重写,我们又需要B视图能够有效地从A视图产生。这样,编译器要求类的对象具有某种灵活的结构。
12.3.1 单一继承的编译方案
- 必须解释编译器是怎样有效地实现动态绑定的
- 编译器为每个类建立一个方法表,它们包含一个类或它的超类中所有定义为virtual的方法的入口
- 每个对象在C程序中有对应的结构,现在为这样的结构增加一个域,该域是方法表的指针
- 继承类方法表的产生:首先拷贝基类的方法表,被重新定义的方法由新的定义覆盖;然后,新引入的方法被追加到这张表上
12.3.2 重复继承的编译方案
- 重复继承对语言定义和编译器设计来说,都具有很大的挑战性
- B1和B2间的冲突与矛盾
- 重复继承
- 可以有多个实例
- 只能有一个实例