2014-02-11 2 views
0

별도의 헤더가있는 두 클래스가 있습니다 (class Rendererclass Texture). Texture 인스턴스는 Renderer의 메모리 풀에있는 일부 데이터를 관리하기 위해 설계 되었기 때문에 Texture 인스턴스는 Renderer 인스턴스와 독립적으로 존재할 수 없습니다. Texture 인스턴스에 대한 핸들을 얻으려면 Renderer::loadTexture을 올바른 파일 이름으로 호출하고 Renderer은 파일 이름이 일치하는 Texture 개체 데이터베이스를 검색하고 일치하는 항목이없는 경우 새 텍스처를 인스턴스화합니다.클래스 델라clation의 순환 종속성

//renderer.h 
#include "texture.h" 
class renderer 
{ 
public: 
    Texture* loadTexture(std::string fileName); 
private: 
    std::map<std::string, Texture*> textureDb; 
}; 

//texture.h 
class Texture 
{ 
public: 
    Texture(std::string imageFileName); 
}; 

class Texture 개인의 생성자를 만들기 위해 논리, 그리고 class Renderer의 친구로 Texture * Renderer::loadTexture(std::string filename)를 선언 할 것이라고 나에게 발생했습니다 texture.h 경우

//renderer.h 
#include "texture.h" 
class renderer 
{ 
public: 
    Texture* loadTexture(std::string fileName); 
private: 
    std::map<std::string, Texture*> textureDb; 
}; 

//texture.h 
class texture; 
#include "renderer.h" 
class Texture 
{ 
private: 
    Texture(std::string imageFileName); 
    Texture(const Texture &); 
    friend Texture* loadTexture(std::string); 
}; 

그러나 이것은 단지 컴파일 class Texture에는 class Renderer이 이미 정의되어 있어야하므로 renderer.h를 포함하기 전에 항상 포함됩니다. 이것을 막는 가장 좋은 방법은 무엇입니까? 두 경비원 모두 포함 된 경비원이지만 간결함을 위해 여기서는 생략되었습니다.

답변

1

위의 코드에서 맨 먼저, 가능한 경우 forward-declare. 이것은 조금 도움이 될 것입니다.

// Renderer.h 
class Texture; 

class Renderer { 
    ... 
}; 

// Renderer.cpp 
#include "Renderer.h" 
#include "Texture.h" 

... 

// Texture.h 
//class Renderer; // looks like this isn't needed 

class Texture { 
    ... 
}; 

// Texture.cpp 
#include "Renderer.h" 
#include "Texture.h" 

... 

전달 선언을 사용하면 렌더러 클래스 헤더의 텍스처에 대한 포인터를 선언 할만큼 충분해야합니다. 이 시점에서 필요한 모든 것 같습니다. 나머지는 Renderer.cpp로 밀어 넣으십시오.

다음으로 친구를 피하십시오. 그러나이 경우에는 허용 될 수 있습니다.

마지막으로 순환 의존성은 결코 좋은 일이 아닙니다. 디자인을 약간 변경할 수 있는지 확인하십시오. 순환 종속성을 깨뜨리기 위해 인터페이스 또는 추상 기본 클래스를 도입 할 수 있는지 확인하십시오. Renderer가 Texture에 전혀 의존 할 필요가없는 것처럼 보입니다. 대신

, 다음 ITexture 인터페이스의 일종에 의존 렌더러를 다시 작성하고, 텍스처가 ITexture을 구현하자

class ITexture 
{ 
    // no data members 
    // no method bodies 
    // only pure virtual method declarations 
}; 

class Renderer 
{ 
public: 
    ITexture* loadTexture(std::string fileName); 
private: 
    std::map<std::string, ITexture*> textureDb; 
}; 

class Texture : public ITexture 
{ 
    ... 
}; 
+0

는 "당신은 약간의 설계를 변경할 수있는 경우를 참조하십시오." Texture는 클래스 렌더러에 의존하지만 다른 방법은 아닙니다. 모든 소유 관계와 데이터로드를 자동으로 처리하는 리소스 관리 시스템을 작성했습니다. – jms