2011-08-01 1 views
17

좋아요, 제목은 한 마디로, 아마도 Google 또는이 사이트를 통해 답변을 찾는 것이 어려웠던 것 같습니다. 그냥 올바르게 문제를 표현하는 방법을 모르겠지만 여기에 간다 :오버로드 된 함수를 해당 다형성 인수와 일치 시키십시오.

SimpleOpenGLRenderer 클래스의 일련의 메서드는 모두 Model 클래스를 확장하는 단일 인수를가집니다. 따라서 모델의 유형에 따라 렌더러는 렌더링 방법을 알고있는 올바른 메서드를 호출합니다.

#include <stdio.h> 

class Model {}; 

class Cube : public Model {}; 

class Sphere : public Model {}; 

class Renderer 
{ 
    public: 
    virtual void renderModel(const Model& model) = 0; 
}; 

class SimpleOpenGLRenderer 
{ 
    public: 
    void renderModel(const Cube& model) 
    { 
     printf("Render the cube.\n"); 
    } 

    void renderModel(const Model& model) 
    { 
     printf("Throw an exception, my renderer does not support the model type you have provided.\n"); 
    } 

    void renderModel(const Sphere& model) 
    { 
     printf("Render the sphere.\n"); 
    } 
}; 

int 
main(int argc, char** argv) 
{ 
    Cube cube; 
    Model& model = cube; 
    SimpleOpenGLRenderer renderer; 

    renderer.renderModel(cube); 
    renderer.renderModel(model); 
} 

예제의 출력은 다음과 같습니다 : 여기에 문제를 기반으로 단순화 된 실행 예입니다

Render the cube. 
Throw an exception, my renderer does not support the model type you have provided. 
계획대로이 작동하지 않는 것을 더 노련한 C++ 개발자에게 명백한 것처럼 보일 수 있습니다

하지만, 그것은 단지 나에게 이해가되지 않는다. 런타임에 렌더러에 전달 된 Model의 정확한 유형을 알 수 없습니다 (따라서이를 해결하기 위해 오버로드를 시도 함). Java 백그라운드에서 왔을 때, 저는이 기술을 Java에서 사용했습니다. 호출 된 메소드는 런타임 인수의 유형과 가장 일치하는 메소드입니다. C++에서는 참조가 컴파일 타임 유형과 일치하는 것으로 보입니다. 비록 그 참조가 내 생각에 다른 함수와 더 잘 일치하는 하위 클래스가 될지라도.

지금까지 필자는이 런타임 유형을 당연하게 받아 들였습니다. 그것은 단순히 C++에 존재하지 않습니까? 아니면 잘못된 방향으로 가고 있습니까? 그것을 달성하기 위해 C++에서 다르게해야할까요?

감사합니다.

게리.

답변

17

C++에서 오버로드는 정적 유형의 인수를 기반으로 컴파일 타임에 해결됩니다. Renderer 기본 클래스 SimpleOpenGLRenderer가 현재 수행하는 모든 오버로드를 포함 할 필요가 있다고

class Model { 
    virtual void dispatchRender(Renderer &r) const = 0; 
}; 

class Cube : public Model { 
    virtual void dispatchRender(Renderer &r) const { 
     r.renderModel(*this); // type of "this" is const Cube* 
}; 

int main() { 
    Cube cube; 
    Model &model = cube; 
    SimpleOpenGLRenderer renderer; 
    cube.dispatchRender(renderer); 
} 

참고 :

사용 될 수있는 "더블 파견"으로 알려진 기술이있다. SimpleOpenGLRenderer에 특정하게 지정하려면 Model에 단순 특정 발송 기능을 넣거나이 기술을 무시하고 대신 을 SimpleOpenGLRenderer::renderModel에 반복적으로 입력하여 유형을 테스트 할 수 있습니다.

+2

감사합니다. 나는 그 패턴을 전에 사용하지 않았다. Java에서는별로 일반적이지 않을 수도 있습니다. 몇 가지 테스트를했는데 아마'dynamic_cast' 솔루션으로 넘어갈 것입니다. 나는 더 우아한 무언가를 원했지만 double-dispatch/visitor 패턴은 온갖 종류의 의존성과 밀접한 커플 링을 소개하는 것처럼 보였습니다. –

1

동적 유형을 기반으로하는 "런타임 오버로드"의 경우 visitor pattern을 사용할 수 있습니다.

+0

아, 링크 주셔서 감사합니다, 나는 그것을 잊어 버렸습니다. 이제 링크를 훔쳤습니다. 그 사람. :-) –

2

코드에서 함수 오버로드는 정적 형식의 인수를 기반으로 해결됩니다.

아마도 방문자 패턴에 매우 가까운 double-dispatch 메커니즘이 필요합니다. 이러한 읽기 :

1

귀하의 코드는 실행시의 형태 매칭의 좋은 후보입니다, 당신이 그것을 사용하는 경우. 여기에 CubeModel&에 입력하고 renderModel()에 간단히 전달합니다.지금까지 컴파일러가 런타임 유형을 사용할 기회를 얻지 못했습니다. 오히려 정적 유형의 객체에 의존합니다.

2 가지 방법으로 런타임 유형 검사를 사용할 수 있습니다. 하나는 dynamic_cast<>을 사용하고 다른 하나는 Model에 인터페이스 메소드를 제공합니다. 즉

+0

정적 유형의 해상도를 더 잘 고려한 것이 없기 때문에'dynamic_cast' 솔루션을 사용할 것이라고 생각합니다. '모델'이 렌더링을 담당하는 것을 원하지 않습니다. 왜냐하면 저는 이미 다른 방식으로 렌더링을 수행하는 10 개의 다른'렌더러 (Renderer) '를 가지고 있기 때문입니다. –

0

C++에서 호출 할 오버로드의 해상도는 컴파일 타임에 완료됩니다.

효과적인 구현을 다형 인수 유형에 따라 수행하려면 해당 인수를 참조해야합니다. 즉 인수에 가상 메소드를 호출해야합니다.

여기서 가장 깨끗한 방법은 visitor pattern입니다. SimpleOpenGLRenderermodel.renderOn(*this) 메소드를 호출 할 수 있습니다. 그런 다음 Model::renderOn은 가능한 모든 유형의 렌더러에 대해 하나의 오버로드 집합이거나 dynamic_cast을 사용하여 렌더러 유형을 찾는 단일 가상 메서드입니다. 어떤 식 으로든 은 렌더러에서을 콜백하지만, 이제이 렌더러는 렌더러의 유형과 유형 자체를 알고 있으며, SimpleOpenGLRenderer::renderCube과 같은 매우 구체적인 렌더링 방법을 호출 할 수도 있습니다.

건배,

0

다른 해결책은 원하는대로 정확하게 수행 할 수 있습니다. 하지만 제 의견에는 복잡성이 있습니다. 문제가 설명 된대로라면 솔루션의 아키텍처를 변경하는 것이 좋습니다. 렌더러가 모델 작업을하려고하지 않습니까? 내가보기에는 일종의 과부하가 스위치 문을 생성했습니다.

어떻게 아마도 몇 가지 클래스를 제공하는 더 원시적 인 그리기 방법을 사용하여, 스스로가 렌더링 모델을 만드는 약 :

class Cube : public Model { 
    render(RenderTool& tool) { 
    tool.renderCube(); //or even more low level 
    } 
}; 

class SimpleOpenGLRenderer { 
    public: 
    RenderModel(Model& model) { 
    model.render(renderTool); 
    } 
    private: 
    SomeOpenGLRenderingTool renderTool; 
}; 
+0

다른 방법보다 더 간단하지는 않습니다. '도구'를 사용하여 렌더링을 수행하는 경우 '렌더러'는 무엇입니까? 그것은 원치 않는 중간 사람처럼 느껴집니다. 'Model'이 렌더링을 담당하는 것을 원하지 않습니다. 렌더링은 다양한 그래픽 API를 사용하는 등 다양한 방법으로 수행 될 수 있습니다. 'Model'의 책임은 단순히 기하학을 기술하는 것입니다. –

+0

정보 전문가의 원칙을 고수하려고합니다. 이 경우 모델은 모양이 어떻게되는지를 아는 유일한 사람입니다. 외부 객체를 만들기 위해 유형을 전환하면 IMO가 캡슐화를 불필요하게 위반하게됩니다. 렌더러가 유효한 것은 유효한 질문입니다. IMO 아마도 모델은 렌더러를 사용해야하며 그렇지 않은 경우 렌더러를 사용해야합니다. – daramarak

관련 문제