개발 노트 오브젝트 캐스팅 2017/09/05 16:48 by cagetu

멀티 플랫폼용 클래스를 만들거나 멀티 렌더러용 클래스를 작성할 때, 다음과 같은 형태로 작성할 때가 많다.

class IVertexBuffer
=> class DX9VertexBuffer
=> class GLESVertexBuffer
=> class VulkanVertexBuffer

그리고, 사용하는 입장에서 IVertexBuffer* m_VertexBuffer; 형태의 기본형으로 가지고 있게 된다.

사용하는 시점이 되었을 때, 각 플랫폼 상황에 맞게 캐스팅을 해서 사용해야 하는 필요가 발생하게 된다. (물론, IVertexBuffer 객체 안으로 encapsulation 하는 것이 가장 아름다운 상황이 될 수 있겠지만, 캐스팅을 해야 하는 상황이 발생하게 된다.)

VulkanVertexBuffer* vertexBuffer = static_cast<VulkanVertexBuffer*>(m_VertexBuffer);

작성하는 사람이 "이 상황에서는 이렇게 무조건 변환될거야!"라고 가정하고 안전하다고 판단해서 강제로 캐스팅을 한다고 하더라도, 예상하지 못한 문제가 발생할 수 있다. 

VulkanVertexBuffer* vertexBuffer = m_VertexBuffer->Type() == VULKAN ? static_cast<VulkanVertexBuffer*>(m_VertexBuffer) : nullptr;

이런 형태로 플랫폼타입을 명시하도록 하고, 좀 더 안전하게 캐스팅할 수도 있다.

VulkanVertexBuffer* vertexBuffer = m_VertexBuffer->ToVulkan();

이런 형태로 플랫폼별로 재정의를 해서 사용할 수도 있다. 많은 엔진에서 캐스팅을 피하기 위해서, 이런 방식을 많이 사용한다. 

뭔가 조금 더 깔끔한 방법이 없을까?를 생각하다가, 초창기 작업했던 것들이 생각이 났다. [Cindy 개발 일지] - ObjectSystem처럼 최소한의 객체 시스템을 만들어서 추가하는 것이다. 일단 캐스팅에 대해서는 RTTI만 있으면 되며, RTTI를 통해서 상속 계층 정보를 얻고, 그 정보를 이용해서 Casting을 이용하는 것이다.

VulkanVertexBuffer* vertexBuffer = DynamicCast<VulkanVertexBuffer>(m_VertexBuffer);

이런 결과로 만들어질 수 있다.

이전에 만들어놓은 작업물이 있어서 추가 작업없이 그냥 사용하면 되었고, 개인적으로 이런 모습을 좀 더 선호하기 때문에 이 방법을 선택했다. 만약 그렇지 않았다면, m_VertexBuffer->ToVulkan() 이런 방식으로 작업했을 것 같다.

ObjectSystem에 추가적으로 Seriailize 정도는 구현을 하면 좋을 것 같은데, Reflication과 Serialization 내용도 다시 리뷰해봐야겠다.

그래도 과거의 내가 한 공부가 헛된 일은 아니었나보다.. ㅎㅎ

덧글

댓글 입력 영역



메모장

내가 먼 훗날에 이 글들을 보았을 때, 좋은 추억이 될 수 있기를...

나를 위해... 나에게 쓰는...

msn: cagetu@hotmail.com
mail: cagetu79@gmail.com
twitter: twitter.com/cagetu
facebook: facebook.com/cagetu