1C与C++的区别:
在C语言中,“数据”和“处理数据的操作(函数)”是分开来声明的,其语言本身并没有支持“数据和函数”直接的关联性。程序性:由一组“分布在各个以功能为导向的函数中”的算法所驱动,它们处理的是共同的外部数据。
而C++采用ADT(abstract data tpye)或class hierarchy的数据封装。加上封装后,C++在布局以及存取时间上的主要额外负担是由virtual引起的,包括两个方面:
- virtual function机制(用以支持一个有效率的“执行期绑定”(runtime binding))
- virtual base class(用以实现“多次出现在继承体系中的base class,有一个单一而被共享的实体”)。
2、C++对象模式
C++中有两种class data members:static、nostatic,以及三种class member functions:static、nonstatic 和virtual。
- nonstatic data members被配置于每一个class object之内;
- static data members则被存在在所有calss object之外;
- static和 non static function members也被放在所有class object之外;
virtual function则以两个步骤支持:
(1)virtual table(vtbl):每个class 产生出一堆指向virtual functions的指针,放在该表格内。
(2)vptr:每个class object 被添加一个指向相关virtual table的指针。vptr的设定和重置都由每个class 的constructor、destructor和copy assignment运算符自动完成。每个class所相关的type_info object(用以支持runtime type identification)也经由virtual
table被指出来,通常放在表格第一个slot处。
举例:
#include <iostream>
using namespace std;
class Point
{
public:
Point (float xval);
virtual ~Point();
float x() const;
static int PointCount();
protected:
virtual ostream& print(ostream &os) const;
float _x;
static int _point_count;};
下图给出一个基本C++对象模型:
(1)float _x;被放在class Point之内。
(2)static int _point_count; Point (float xval); float x() const;static int PointCount();不在class Point之内,即放在所有class object外面。
(3)virtual table有两项,表示 virtual ~Point();virtual ostream& print(ostream &os) const;
3、加上继承(单一继承、多重继承、虚继承)
两种对象模型:
(1)简单对象模型:derived class object内的一个slot指出每一个base class (该slot内含base class subobject的地址)。优点是class object的大小不会因base classes的改变而受到影响。缺点是因为间接性而导致空间和存取时间上的额外负担。
(2)base table模型:很像virtual table 内含每一个virtual function的地址,base class table的每一个slot含有一个相关的base class地址。每一个class object内含有一个bptr,被初始化后指向其base class table。
不管采用那种模型,“间接性”的级数都将因为继承的深度而增加。
单一继承、多重继承:
C++最初采用的继承模型并不运用任何间接性:即base class subobject的data members被直接放在derived class object中。这(直接复制模型)提供了对base class 最紧凑而最有效率的存取。缺点是base class members的任何改变后,所有用到此base class或其derived class的objects者必须重新编译。
虚继承:
需要一些间接性的base class表现方法。其原始模型是在class object中为每一个有关联的virtual base class 加上一个指针。其他演化的模型则若不是导入一个virtual base class table,就是扩充原来已经存在的virtual table,以便维护每一个virtual base class的位置。
总结:
对于单一继承、多重继承采用直接复制模型,对于虚继承则(在直接复制模型的基础上)选择两种间接性模型之一。在虚继承的情况下,base class不管在继承串链中被派生多少次,永远只会存在一个实体(subobject)。
4、对象的差异
C++程序设计模型直接支持三种programming paradigms(编程范式):
(1)程序模型(procedural model):与C一致;
(2)抽象数据类型(abstract data type model,ADT):抽象数据类型是与表示无关的数据类型,是一个数据模型及定义在该模型上的一组运算;其处理的是一个拥有固定而单一的类型的实体,在编译时期就已经完全定义好了。
(3)面向对象模型(object-oriented model):在此模型中有些彼此相关的类型,通过一个抽象的base class(用以提供公共接口)被封装起来。原则上,被指定的object的真实类型在每一个特定执行点之前无法解析。在C++中,只有通过pointer和reference才能够完成。
在需要多态时,对一个base class object,只有通过pointer或reference的间接处理,才支持OO程序设计所需的多态性质。
C++支持多态的方法:
- 经由一组隐含的转换操作。
- 经由virtual function机制。
- 经由dynamic_cast和typeid运算符。
经由一个共同的接口来影响类型的封装,这个接口通常被定义在一个抽象的base class中。这个共享接口是以virtual function机制引发的,它可以在执行期根据object的真正类型解析到底是哪一个函数实体被调用
- “指向不同类型的各指针”间的差异,既不在其指针表示方法不同,也不再其内容(代表一个地址)不同,而在其所寻址出来的object类型不同。(“指针类型”会教编译器如何解释某个特定地址中的内存内容及其大小)
- void*类型的指针只能够含有一个地址,而不能通过它操作所指的object。(无类型,不知道其涵盖的地址空间)
- Pointer或reference之所以支持多态,是因为它们并不引发内存中任何“与类型有关的内存委托操作(type-dependent commitment)”;会受到改变的只是它们所指的内存的“大小和内容解释方式”。