《深入探索C++对象模型》笔记之第一章关于对象

1.0

C++的编程范式一共有三种,分为程序模型(procedural model)、抽象数据类型模型(abstract data type model, ADT)和面向对象模型(object-oriented model)。这三种范式不止在程序风格上有显著的不同,在程序的思考上也有明显的差异。
在C++中加上封装后的布局成本:与C struct相比并没有增加成本。在C++中,布局及存取时间上的主要额外负担来自virtual引起的,包括:
 - virtual function机制 用以支持一个有效率的“执行期绑定”
 - virtual base class 用以实现“多次出现在继承体系中的base class,有一个单一而被共享的实例”

1.1 C++对象模型

在C++中,有两种class data member: static 和 nonstatic, 以及三种class member function: static、nonstaic 和 virtual。
在Stroustrup当初设计的模型中,Nonstatic data member 被配置于每一个class object之内,static data member 则被存放在个别class object 之外。static 和 nonstatic function member 也被放在个别的class object 之外。Virtual function 则以两个步骤支持之:
 1. 每个 class 产生一堆指向 virtual function 的指针,放在表格中。这个表格被称为 virtual table(vtbl)。
 2.  每个class object被安插一个指针,指向相关的 virtual table。通常这个指针被称为 vptr。vptr 的设定和重置都由每一个 class 的 constructor、destructor 和 copy assignment运算符自动完成(在第五章详细讨论)。每一个 class 所关联的 type_info object 也经由 virtual table 被指出,通常放在表格的第一个slot。 

继承模型

C++最初的继承模型:base class subobject 的 data member 被直接放置于 derived class object 中。这提供了对 base class members 最紧凑而且最有效的存取。但是,base class member 的任何改变,使得所有用到“此base class 或者其 derived class 之 object”者都必须重新编译。
对于 virtual base object,需要一些间接的 base class 表现方法(我们在第三章详细讨论)。

对象模型如何影响程序

举个栗子,看下面函数,其中class X定义了一个 copy constructor、一个virtual destructor 和一个 virtual function foo:
X foobar()
{
    X xx;
    X *px = new X;
    //foo 是一个 virtual function
    xx.foo();
    px->foo();

    delete px;
    return xx;
}

这个函数有可能被转化为:

//可能的内部转换结果
//虚拟C++代码
void foobar(X &_result)
{
    //构造 _result
    // _result 用来取代 local xx...
    _result.X::X();

    //扩展X *px = new X;
    px = _new( sizeof(X) );
    if( px != 0 )
        px->X::X();

    //扩展 xx.foo() 但不使用virtual
    foo( &_result );

    //使用 virtual 机制扩展 px->foo();
    ( *px->vtbl[2] )( px );

    //扩展 delete px
    ( *px->vtbl[1] )( px );
    _delete( px );

    //无须使用 named return statement
    //无须摧毁 local object xx
    return;
}

对象的差异

C++以下列方法支持多态:

  • 经由一组隐式的转化操作。例如把一个 derived class 指针转化为一个指向其 public base type 的指针:
    shape *ps = new circle();
  • 经由 virtual function 机制
  • 经由 dynamic_cast 和 typeid 运算符

    需要多少内存才能表示一个 class 呢?一般而言需要:

  • 其 nonstatic data members 的总和大小

  • 加上任何由于 alignment 的需求而填补上去的空间
  • 加上为了支持 virtual 而由内部产生的任何额外负担

指针的类型
指向不同类型的指针,它们之间有什么区别?
以内存需求角度来说,并没有什么不同,都是要有足够的内存来放置一个机器地址(通常是一个word)。
区别在于,涵盖的地址大小不同。例如有:

int a;  //假设a的地址为 1000
double b; //假设b的地址为 2000
int *pInt = &a; //pInt:1000
double *pDouble = &b; //pDouble:2000
++pInt; //pInt: 1004
++pDouble; //pDouble: 2008
可以看到,pInt的涵盖的内容大小是一个sizeof(int) = 4,pDouble涵盖的大小是一个sizeof(double)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值