更多 C++ 惯用法/能力查询
外观
在运行时检查对象是否支持某个接口。
将接口与实现分离是良好的面向对象软件设计实践。在 C++ 中,接口类 惯用法用于将接口与实现分离,并使用运行时多态性调用任何抽象的公共方法。扩展接口类惯用法中的示例,具体类可以实现多个接口,如下所示。
class Shape { // An interface class.
public:
virtual ~Shape();
virtual void draw() const = 0;
//...
};
class Rollable { // One more interface class.
public:
virtual ~Rollable();
virtual void roll() = 0;
};
class Circle : public Shape, public Rollable { // Circles roll - concrete class.
//...
void draw() const override;
void roll() override;
//...
};
class Square : public Shape { // Squares don't roll - concrete class.
//...
void draw() const override;
//...
};
现在,如果我们得到一个指向抽象类 Rollable
的指针的容器,我们可以简单地对每个指针调用 roll 函数,如接口类惯用法中所述。
std::vector<Rollable *> rollables;
// Fill up rollables vector somehow.
for ( Rollable * rPtr : rollables )
rPtr->roll();
有时,我们无法提前知道对象是否实现了特定的接口。这种情况通常发生在对象从多个接口类继承时。为了在运行时发现接口的存在与否,可以使用能力查询。
在 C++ 中,能力查询通常表示为在无关类型之间进行 dynamic_cast
。
Shape *s = getSomeShape();
if (Rollable *roller = dynamic_cast<Rollable *>(s))
roller->roll();
这种 dynamic_cast
的用法通常称为交叉转换,因为它试图跨越层次结构进行转换,而不是向上或向下层次结构。在我们关于形状和可滚动对象的示例层次结构中,dynamic_cast
到 Rollable
仅对 Circle
成功,而对 Square
则不成功,因为后者没有从 Rollable
接口类继承。
过度使用能力查询通常表明面向对象设计存在缺陷。
- Dewhurst,Stephen C. "能力查询"。C++ 常识。ISBN 0321321928.