2013-08-01 2 views
1

내 C++ 프로젝트에는 Engine 클래스, Renderer 클래스 및 Object 클래스가 있습니다.순환 종속성 수수께끼

Renderer의 인스턴스는 Object의 인스턴스를 렌더링합니다. 그러나 Object의 인스턴스는 자신을 추가하거나 렌더링 할 항목 목록에서 자신을 제거합니다.

유용성의 관점에서 Object의 인스턴스를 순환 종속성없이 그려야하는지 여부를 설정할 수 있어야합니다.

나는이 문제에 대한 가능한 해결책을 가지고 있지만 그것은 좋은 생각이다 모르겠어요 :

게임의 업데이트주기는 Update() 함수를 호출하는 Engine 클래스에 Update() 기능을 통해 이루어집니다

모든 개체에 대해 Object의 각 인스턴스에 대해 Update() 함수를 호출 할 때 Object 클래스의 두 개의 부울 변수를 확인하도록 설정할 수 있습니다. 하나는 그려야하는지, 실제로 그려지 는가를위한 것입니다. 이렇게하면 Object의 인스턴스가 필요에 따라 렌더링하기 위해 추가되거나 제거 될 수 있습니다.

이렇게하면 좋을까요? 이 방법은 효율적입니까 아니면 원형 의존성이없는 더 좋은 방법입니까?

편집 : 나는 더 명확하게 내 질문을 다시 작성하고 아마 더 관련이었고, 여기에서 더 복잡한 일을 방지하기 위해 새로운 질문에 두 번째 부분을 이동 한 .

+0

내가 제대로 이해하면 나도 몰라 ...하지만 내 생각 'Renderer'에 대한 참조를'Object'에 추가하지 말아야합니다. 대신, Object :: Update가 호출 될 때, 객체가 드로잉리스트에 추가/제거되어야하는지 여부를 리턴하고,'Engine '이'Renderer'리스트에서 삽입/삭제를 수행하도록합니다. 그런 식으로 의존성은'Engine -> Renderer'이고 여러분은 이미 그것을 가지고 있습니다. – rodrigo

+0

이것은 내 질문에서 언급했듯이 내가 생각해 낸 대안이지만, 비효율적 인 방법인지 또는 더 나은 대안이 있는지 확실하지 않습니다. – Interminable

+0

포인터 나 참조 만 사용하면 클래스를 다른 헤더로 전달 선언 할 수 있으며 실제 헤더를 cpp에 포함시킬 수 있습니다. 내가 너무 신경 쓰지 않을 정도로 당신이이 수업들을 완전히 분리 할 필요가있는 것처럼 들리는 것은 듣지 않습니다. – sje397

답변

0

정말 의도를 이해합니다. 그러나, 나는 원래의 질문을 다시 방문하고 싶은 :

현재 개체의 인스턴스에 대한 순서로 그려 질, 그것을 그리는 객체의 렌더러의 목록의 인스턴스에 자신을 추가 할 필요가있다. 이 은 Renderer의 인스턴스에 대한 포인터가 필요하다는 것을 의미하지만 Renderer 도 그릴 수 있도록 Object에 대해 알아야합니다.

왜 이것이 문제입니까? 심지어 청소기는 인터페이스 클래스를 사용하는 것, 비록

class Object; 
class Renderer; 
class Engine; 

: 당신은 그냥 포인터를해야하는 경우, 선행 클래스의 타입을 선언 할 수 있습니다.

편집 : 내가 제대로 이해하고 수행, 문제는이 오브젝트하는 렌더링 인스턴스를 전달하려는, 그래서 객체가 렌더러를 사용하여 자신을 그릴 수 있습니까?

무엇 다음 인터페이스 클래스에 대한 :

class Paintable 
{ 
    public: 
     virtual void paint(Renderer *) = 0; 
}; 

class Object : public Paintable 
{ 
    ... 
} 

귀하의 모든 페인트 가능 객체가 인터페이스에서 연장됩니다. 이 방법으로 Renderer 클래스는 Objects 벡터를 유지할 필요는 없지만 Paintable에 대한 포인터는 벡터로 유지할 수 있습니다. (예 :렌더러는 더 이상 객체에 종속되지 않습니다.

ANSWER : 두 번째 설명 선택의 여지가 없습니다. Object의 내부 데이터 (색상, 위치 등) 및 렌더러 핸들에 액세스하려면 렌더링 코드가 필요합니다. 객체의 내부 데이터에 액세스하는 Renderer의 코드가 선택됩니다. Renderer가 다른 객체를 처리하는 다른 코드를 가질 필요가 있고 객체의 private 멤버에 액세스 할 필요가 있기 때문에 이것은 잘못된 생각입니다. 다른 방법은 렌더러 핸들을 사용하여 렌더링 할 수있는 지능적인 객체를 사용하는 것입니다. 그래서 렌더러는 rendererer.paintLine (...) 등을 호출 할 수 있습니다. 인터페이스 클래스를 사용하는 것은 깔끔합니다. 렌더러는 보유하고있는 객체에 대한 지식이 필요하지 않기 때문입니다.

+0

요점은 'Engine'인스턴스 또는 'Renderer'인스턴스에 포인터를 전달하고 싶지 않다는 것입니다. 현재 내가하는 일은 이미'Object' 클래스에서'Renderer'의 선언을 사용하고 있습니다 만,'Engine'이나'Renderer'의 인스턴스에 대한 포인터를 인스턴스에 전달하지 않아도됩니다. 'Object'를 전혀 사용하지 않습니다. 이것은 피하려고하는 순환 종속성입니다. – Interminable

+0

이상적으로'Renderer'에 대해 알지 못하도록'Object'를 선호하지만, 내 대답에서 제안한 대안이 좋은 아이디어인지 아니면 더 나은 대안이 있는지는 모르겠습니다. (그리고 그렇다면 왜). – Interminable

+0

나는 달성하고자하는 것을 더 분명하게하려고 내 질문을 다시 작성했다. – Interminable

0

당신은 렌더링에서 상속하는 객체를 원하고, 렌더러, 객체 (아래 참조)하지 렌더링의 인식 만에 것입니다 :

#include <iostream> 
#include <list> 

struct Renderer; 

struct Rendered 
{ 
    virtual void renderMe(Renderer&) = 0; 
    protected: 
    //Renderer won't delete me... 
    virtual ~Rendered(){} 
}; 

struct Object : Rendered 
{ 
    virtual void renderMe(Renderer&) 
    { 
    std::cout << "I'm rendered!" << std::endl; 
    } 
}; 

struct Renderer 
{ 
    void add(Rendered& r) 
    { 
    renderList_.push_back(& r); 
    } 
    void remove(Rendered& r);//...use your imagination 

    void render() 
    { 
    for(std::list<Rendered*>::iterator i = renderList_.begin(); i != renderList_.end(); ++i) 
    { 
     (*i)->renderMe(*this); 
    } 
    } 
    private: 
    std::list<Rendered*> renderList_; 
}; 

struct Engine 
{ 
    Renderer& renderer_; 
    Object myObject_; 
    Engine(Renderer& r) 
    : renderer_(r) 
    { 
    renderer_.add(myObject_); 
    } 
    ~Engine() 
    { 
    renderer_.remove(myObject_); 
    } 
}; 

int test() 
{ 
    Renderer r; 
    Enginer e(r); 
    r.render(); 
    return 0; 
} 
+0

예제를 올바르게 읽는다면'Object' 클래스는'Rendered'를 상속 받지만 여전히'Renderer'에 대한 참조를 전달해야합니까? – Interminable

+0

예,하지만 Renderer는 그것이 객체임을 모릅니다. 렌더러에게 그것은 렌더 된 것입니다 ... 따라서 종속성은 상속에 의해 반대로됩니다. 이제 Renderer는 추상 형식에 의존하며 Object에 대해 알 필요가 없습니다. –

+0

나는 뭔가를 놓칠지도 모른다. 그러나 내가 지금 가지고있는 것과 비교했을 때 이것의 장점은 무엇인가? 질문에 대한 나의 생각은'Object'가'Renderer'에 대해 알아야 할 필요성을 제거하는 것이 었습니다. – Interminable