More C++ Idioms/Capability Query
Capability Query
[edit | edit source]Intent
[edit | edit source]To check at runtime whether or not an object supports an interface.
Also Known As
[edit | edit source]Motivation
[edit | edit source]Separating interface from implementation is a good object oriented software design practice. In C++, the Interface Class idiom is used to separate interface from implementation and invoke the public methods of any abstraction using runtime polymorphism. Extending the example in the interface class idiom, a concrete class may implement multiple interfaces as shown below.
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;
//...
};
Now, if we are given a container of pointers to abstract class Rollable
, we can simply invoke the roll function on every pointer, as described in the interface class idiom.
std::vector<Rollable *> rollables;
// Fill up rollables vector somehow.
for ( Rollable * rPtr : rollables )
rPtr->roll();
Sometimes it is not possible to know in advance whether or not an object implements a particular interface. Such a situation commonly arises if an object inherits from multiple interface classes. To discover the presence or absence of the interface at runtime, a capability query is used.
Solution and Sample Code
[edit | edit source]In C++, a capability query is typically expressed as a dynamic_cast
between unrelated types.
Shape *s = getSomeShape();
if (Rollable *roller = dynamic_cast<Rollable *>(s))
roller->roll();
This use of dynamic_cast
is often called a cross-cast, because it attempts a conversion across a hierarchy, rather than up or down a hierarchy. In our example hierarchy of shapes and rollables, dynamic_cast
to Rollable
will succeed only for Circle
and not for Square
, as the later one does not inherit from the Rollable
interface class.
Excessive use of capability queries is often an indication of bad object-oriented design.
Known Uses
[edit | edit source]- Martin, Robert C. "Acyclic Visitor Pattern" (PDF).
{{cite web}}
:|archive-url=
requires|archive-date=
(help)
Related Idioms
[edit | edit source]References
[edit | edit source]- Dewhurst, Stephen C. "Capability Queries". C++ Common Knowledge. ISBN 0321321928.