More C++ Idioms/Capability Query

진영민·2022년 8월 15일
1

More C++ Idioms

목록 보기
9/10

의도

만약 어떤 함수가 다른 함수를 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이다.

sample code

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";
	}
}
profile
코린이

0개의 댓글