Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1664367
  • 博文数量: 607
  • 博客积分: 10031
  • 博客等级: 上将
  • 技术积分: 6633
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-30 17:41
文章分类

全部博文(607)

文章存档

2011年(2)

2010年(15)

2009年(58)

2008年(172)

2007年(211)

2006年(149)

我的朋友

分类: C/C++

2008-07-31 10:56:56

author:d.schmidt@vanderbilt.edu Vanderbilt University

动态绑定的动机

人们遇到2种情况:知道想要什么样的类接口,但是不知道最合适的表述形式;或者知道想要什么样的算法,但是不知道特定操作如何被实现。
于是,人们自然地想到,放置某种形式的抽象占位(place-holder)或许是合适的.

动态绑定不比函数指针更强大,但比它更好理解,更不容易出错.

动态绑定允许程序通过一个基类指针调用通用方法:
class Base{ public: virtual int vf(void);};
Base *bp = /* pointer to a subclass */
bp->vf();
然而,运行时,这个调用会调用子类的特化的方法.
class Derived: public Base{ public: virtual int vf(void);};
Derived d;
bp=&d;
bp->vf(); //invoke Derived::vf()
在C++,这要求通用和特化方法都是虚拟的.

动态绑定带来更好的Flexibility和Extensibility.
- Flexibility='easily recombine existing components into new configurations'
- Extensibility='easily add new components'

动态绑定VS静态绑定
继承的回顾
子类的指针总是可以被用作指向公开继承的基类的指针. Caveat(警告):这种转换可能是不合法的,不安全的.
这时是调用那个方法呢,依赖于绑定的类型.
什么时候动态绑定?什么时候竟态绑定?
采用静态绑定:
[1]当你确信下一级派生类不会动态地改写这个操作(只是重新定义,隐藏)
[2]尽可能地重用具体的数据类型
采用动态绑定:
[1]派生类运行时可能会采用新的方法实现
[2]用于构建动态类型架构

Effeciency和Flexibility是选择时需要考虑的因素.
采用静态绑定,更有效率;动态绑定更灵活.但动态绑定对象难于保存在共享内存中.

C++中,动态绑定通过virtual关键字来标记.

ABC: Abastract Base Class
PVC: Pure Virtual Class

抽象的析构函数的唯一作用是导致该类被定义成ABC--抽象基类。但不会迫使派生类的析构函数也变成抽象的。

在C++中,子类的构造函数会自动调用父类的构造函数。同样,子类的析构函数也会自动调用父类的析构函数。


调用指针指向的方法的机制是什么?
在C++中,就是静态绑定和Virtual Method Tables。在C中,使Method Dispatch Tables。

对象指针有个暗藏的指针属性vptr*

Downcasting是有危险的!
而Upcasting总是OK的。

static_cast其实就是C中的强制类型转换

RTTI(Run Time Type Identification)
RTTI只支持动态绑定的类.RTTI是一种技术,允许程序在运行时查询对象的类型。
RTTI的用法
if(Derived *d=dynamic_cast&b){
  // do
}
else{
  // error
}

dynamic_cast引用失败会报出bad_cast 异常!
try{
  Derived &d = dynamic_castobj;
}catch(bad_cast){
  /*... */
}

陪伴着dynamic_cast<>, C++还提供了typeid()这样一个操作符
typeid(type) yields const Type_info&
typeid(expr) yields const Type_info&

RTTI的例子

Base *bp=new Derived;
Base &br=*bp;

typeid(bp) == typeid(Base*)    //true
typeid(bp) == typeid(Derived*) //false
typeid(*bp)== typeid(Base)     //false
typeid(*bp)== typeid(Derived)  //true
typeid(br) == typeid(Base &)   //false
typeid(br) == typeid(Derived&) //true
typeid(&br)== typeid(Base *)   //true
typeid(&br)== typeid(Derived*) //false

注意,如果比较的是对象的话,参照的实际对象;
反之,如果比较的知识指针,还是参照声明来。






阅读(558) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~