만약 어떤 함수가 다른 함수를 implement한다고 하자.
class Shape{
public:
virtual ~Shape();
virtual void draw() const=0;
};
class Rollable {
public:
virtual ~Rollable();
virtual void roll() = 0;
};
class Square: public Shape{
void draw() const override;
}
이러한 상황에서,
for ( Shape * sPtr : shapers )
sPtr->draw();
이러한 코드를 돌린다고 가정해 보자.
shapers안에는 많은 객체들과 그들의 class가 있을 것이다.
하지만 너무 많은 implement와 class가 있다 보니, 객체가 Shape이라는 클래스를 상속했는지 조차 모를 수 있다.
만약 Shape의 객체들을 모아 놓은 vector에서 객체들을 가져와 roll 함수를 실행시키고 싶다면 어떻게 해야 할까?
런타임에서 이러한 상속을 체크하는 방식이 capability query이다.
Shape *s = SomeShape();
if(Rollable *roller = dynamic_cast<Rollable *>(s))
roller->roll();
먼저, shape의 객체를 가져온다.
해당 객체를 Rollable로 변환하며, 만약 해당 객체가 Rollable을 상속받았을 경우 이상 없이 변환될 것이다.
하지만 Rollable을 상속받지 못했을 경우 해당 함수는 호출되지 않는다.
#include <iostream>
#include <vector>
using namespace std;
class Shape {
public:
virtual void draw() const = 0;
};
class Rollable {
public:
virtual void roll() = 0;
};
class Circle : public Shape, public Rollable {
void draw() const override {
cout << "draw" << "\n";
};
void roll() override {
cout << "roll" << "\n";
};
public:
Circle* getShape() {
return this;
}
};
class Square : public Shape {
void draw() const override {
cout << "shape!" << "\n";
};
public:
Square* getSquare() {
return this;
}
};
int main(void) {
Circle circle = Circle();
Circle* s = circle.getShape();
Square square = Square();
Square* ss = square.getSquare();
vector<Shape *> storage;
storage.push_back(s);
storage.push_back(ss);
for (Shape* sPtr : storage) {
if (Rollable* roller = dynamic_cast<Rollable*>(sPtr))
std::cout << "baaaam!" << "\n";
}
}