您的位置:首页 > 编程语言 > C语言/C++

C++之能力查询

2013-09-07 17:21 211 查看
在大多数情况下,当一个对象出现并开始工作时,它就能够执行我们需要它执行的事情,因为它的能力已经在接口中被明确的定义好了。

class Shape {

public:

virtual ~Shape();

virtual void draw() const = 0;

// ....

};

//````

Shape* s = getSomeShape(); // 获得一个shape,并且叫它去....

s->draw(); // 干活....

这样,我们只管叫这个对象去干活就行了。这很简单,也很高效,正是我们想要的效果。

然而,在实际中并非一切都是这么顺理成章,很多时候我们需要知道(或者测试)一个对象具备什么样的能力。

例如,对于上面的例子我们可能需要一些能够滚动的形状。那么我们写一个Rollable类,然后让具体的Shape类(例如下面的Circle类)多重继承自Shape和Rollable。

class Rollable{

public:

virtual ~Rollable();

virtual void roll() = 0;

};

像这样的类通常是一个接口类(interface class),因为它只指定了接口,如同Java的接口一样。通常来说,这样的类没有非静态成员,没有声明构造函数。一个虚析构函数和一个纯虚函数指明了一个Rollable对象能够做什么。

class Circle : public Shape, public Rollable { // 多重继承,圆形可以滚动

public:

//```

void draw() const;

void roll();

};

当然,并不是所有的Shape类对象都可以滚动

class Square : public Shape { // 单继承,正方形不能滚动

//...

void draw() const;

};

也有一些能滚动的对象却不是一个(not is-a)Shape.

class Wheel : public Rollable {

// ....

};


在我们试图滚动某一个对象之前,我们总是想知道面对的对象是否为Rollable,但是我们并不总是知道这样的对象是否具有这样的能力。在这种情况下,我们需要执行一个能力查询(测试)。在C++中能力查询通常是通过对“不相关”的类型进行dynamic_cast 转换而表达的。

Shape *s = getSomeShape();

Rollable *Roller = dynamic_cast<Rollable*>(s);

这种 dynamic_cast 用法通常称为“横向转型(cross-cast)”,因为它试图在一个类层次结构中执行横向转换,而不是向上或者向下转换。

如果查询成功比如说s实际指向的是圆(或者派生自Rollable的其它Shape),那么转型成功,Roller指向该对象。如果s实际指向的对象是一个Square(或者其它的未派生自Rollable的Shape), dynamic_cast 就会失败(结果返回一个空指针)。

所以可以用以下的代码来进行判断控制。

if ( Rollable *Roller = dynamic_cast<Rollable*>(s) )

roller->roll();

能力查询只是偶尔需要,但它们往往被过度使用。它们通常是糟糕设计的“指示器”。



参考:《C++必知必会》P72 条款27 能力查询
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐