2009-06-23 6 views
3

I가 다음과 같은 기존 클래스 :C 복잡한 상속을 구현 ++

class Gaussian { 
public: 
    virtual Vector get_mean() = 0; 
    virtual Matrix get_covariance() = 0; 
    virtual double calculate_likelihood(Vector &data) = 0; 
}; 

class Diagonal_Gaussian : public Gaussian { 
public: 
    virtual Vector get_mean(); 
    virtual Matrix get_covariance(); 
    virtual double calculate_likelihood(Vector &data); 
private: 
    Vector m_mean; 
    Vector m_covariance; 
}; 

class FullCov_Gaussian : public Gaussian { 
public: 
    virtual Vector get_mean(); 
    virtual Matrix get_covariance(); 
    virtual double calculate_likelihood(Vector &data); 
private: 
    Vector m_mean; 
    Matrix m_covariance; 
}; 
보시다시피

, 인터페이스와 클래스 가우스 행위 있지만 구현이 없습니다. 이것은 모두 정상적으로 작동합니다.

이제 likelihood가 계산되기 전에 calculate_likelihood에 제공된 데이터 벡터가 변경되는 "AdaptedGaussian"클래스를 만들고 싶습니다.

일부 요구 사항 :

  • 가 AdaptedGaussian는
  • AdaptedGaussian는
  • AdaptedGaussian가해야 가능한 모든 가우스 클래스 "의 인스턴스가 될" "포장"또는 할 수 있어야 가우스의 아이 클래스 여야합니다 이미 존재하는 가우스 Object에서 구성 할 수

내가 지금 가지고있는 생각은 다음과 같습니다

class Adapted_Gaussian : public Gaussian { 
private: 
    Gaussian* m_g; 

public: 
    virtual Vector get_mean() { return m_g->get_mean(); } 
    virtual Matrix get_covariance() { return m_g->get_covariance(); } 
    virtual double calculate_likelihood(Vector &data) 
    { 
    //do something with data 
    return g->calculate_likelihood(Vector &data); 
    } 
} 

어쩌면 몇 가지 단점이 있습니다 모든 방법

  • 더미 방법은 가우스 이제까지 확장
  • 하면 새 클래스로 작성이되어야한다 (그리고이 여기에 보여 주었다보다 더) 클래스를 잊어 버리면 불쾌한 버그가 나타날 수 있습니다.

올바른 방법으로이 작업을 수행하고 있습니까? 아니면 이것을 구현하는 더 좋은 방법이 있습니까?

구현되지 않은 모든 메소드를 m_g의 동일한 명명 된 메소드로 표준 위임하는 좋은 방법이 있습니까?

+1

내가 여기에 이해가 안 무엇 : 당신이 정말로 호출 수행을 calculate_likelihood 내에서 "get_covariance"또는 그냥 버그이며 calculate_likelihood를 호출하고 싶습니까 ?? 나는 내 통계가 매우 녹슬 었음을 인정해야한다 ... – Juergen

+0

아이, 그건 실수였다. 고마워, 나는 그것을 고쳤다. –

+0

Btw. calculate_likelihood 정말 무효입니까 ?? 그렇게 생각하지 마라 !! – Juergen

답변

5

좋아,이 어댑터 패턴의 꽤 고전적인 구현이라고 생각합니다. 가우스 클래스의 가상 소멸자를 선언하는 것을 잊지 마십시오. 단점은.

  1. 더미 메소드 문제를 처리하는 Java 클래스 라이브러리는 모든 단일 메소드에 대해 빈 구현을 제공하는 더미 클래스를 만드는 방법입니다. 모든 단일 메서드를 구현하지 않으려는 모든 클래스는이 더미 클래스에서 상속 받고 해당 더미 클래스에 관심있는 메서드를 선택적으로 재정의 할 수 있습니다.
  2. 더 많은 메소드를 사용하여 가우스 클래스를 확장하는 경우 순수 가상 메서드로 선언하면 자식 클래스 파일에 컴파일러 오류가 발생합니다.
0

자바에서는 모든 메소드에 기본 동작을 제공하기 위해 인터페이스와 구현 클래스를 모두 구현하는 것이 일반적입니다. (Joshua Bloch의 java.util 패키지에있는 Collections API 디자인을 참조하십시오.) 아마도 도움이 될 것입니다. 클라이언트는 인터페이스 나 추상 클래스 중 하나를 선택할 수 있습니다.

composition도 시도 할 수 있습니다. 적응 형 가우스의 인스턴스를 하위 클래스로 전달하고 하위 클래스에 동작을 연기합니다.

1

Strategy Pattern으로 해결할 수도 있습니다.

나는이 두피모도 "구성"과 함께이 방향으로 생각하고 있었다. 기본 클래스가 포함하는 다른 객체의 메서드를 호출하는 방식으로 디자인을 변경합니다. 이 개체에는 calculate_likelihood에 대한 코드가 들어 있습니다. 전체 메소드가 지연되거나 수정 만 가능합니다 (두 번째 경우 기본값은 아무 것도하지 않는 것입니다).

예 : (수정 버전)

class Gaussian { 
    private: 
     Cl_Strategy* m_cl_strategy; 

    public: 
     Gaussian(Cl_Strategy* cl_strategy) { 
     m_cl_strategy = cl_strategy; 
     }; 
     virtual Vector get_mean() = 0; 
     virtual Matrix get_covariance() = 0; 
     virtual double _calc_likelihood(Vector &data) = 0; 
     virtual double calculate_likelihood(Vector &data) { 
     m_cl_strategy->do_your_worst(this, data); 
     return _calc_likelihood(data); 
     }; 
}; 

은 내가 한 바로 것을, 내 C + +를 조금 뿌려이다있어, 희망은 ...

_calc_likelihood는 서브 클래스와 calculate_likelihood를 구현할 필요가 모든 결합 함께.

물론이 솔루션은 약간의 오버 헤드를 추가하지만 일부 상황에서는 오버 헤드가 문제가되지 않을 수도 있습니다.

+0

이 아이디어는 완전히 작동하지 않습니다. 모든 하위 클래스는 calculate_likelihood의 자체 구현을 가지므로 해당 데이터가 제공되지 않습니다. 게다가이 기능을 현재 클래스 외부에서 사용하고 싶습니다. 이것은이 기능이 다른 방법/방법으로 구현 될 수 있고 응용 프로그램 실행의 몇 %에서만 사용되기 때문입니다. –

+0

의견에 감사드립니다. 나는 물론 그 문제를 이해하는만큼 많은 것을 암시 할 수있다. 그게 내가 어쩌면 쓴 이유야. 전체 컨텍스트가 코드 스 니펫에서 너무 명확하지 않습니다. 모든 하위 클래스가 calculate_likelihood를 자체적으로 구현할 때, 예제가 작동 할 수있는 방법은 무엇입니까? – Juergen

+0

필자의 예가 효과적이지 않은 이유를 정확히 알 수는 없습니다. calculate_likelihood는 Gaussian에서 가상이므로 (구현되지 않으면 = 0 참조) 실제 객체의 calculate_likelihood 함수가 실행됩니다. Gaussian * 포인터는 항상 Gaussian의 하위 클래스의 인스턴스를 가리 킵니다. –

2

많은 기본적인 패스 스루 기능을 작성하는 것이 지루하고 지루하고 유지 관리 오버 헤드가 추가됩니다. 또한, 포인터 멤버를 갖는 것은 소유 포인터의 평생 관리 문제를 의미합니다 (단순하지만). 아마도 이러한 문제를 해결할 수있는 가장 간단한 방법은 AdaptedGaussian을 템플릿으로 만들어 가우스의 특정 인스턴스에 적용하여 적응시키는 것입니다.

template<class BaseGaussian> class AdaptedGaussian : public BaseGaussian 
{ 
    virtual double calculate_likelihood(Vector &data) 
    { 
     // do something with data 
     return BaseGaussian::calculate_likelihood(Vector &data); 
    } 
}; 

이 가우시안 존재의 기본 작도의 모든 적응 인스턴스에 의존, 또는 적어도 일반적인 생성자 서명에 부합 않습니다.

당신은 너무 오래 XXXGaussian 당신이 적절한 생성자를 추가 할 수 있습니다 복사 가능한 자체를 같이 한 후, 기존 XXXGaussian에서 AdaptedGaussian을 구성하려면 다음

template<class BaseGaussian> class AdaptedGaussian : public BaseGaussian 
{ 
public: 
    AdaptedGaussian(const BaseGaussian& other) : BaseGaussian(other) 
    { 
    } 
    // ... 
}; 
+0

흠, 기존 Gaussian에 대한 포인터 만 가지고있을 때 어떻게 AdaptedGaussian을 만들 수 있습니까? –

+1

아마이 솔루션에서 AdaptedGaussian은 적응 된 특정 유형의 가우스의 인스턴스입니다. 적응 형 대각선 가우스를 원한다면 일반 Diagonal_Gaussian 대신에 AdaptedGaussian 을 만들 것입니다.AdaptedGaussian 이 T 인 경우 AdaptedGaussian 에 대한 포인터와 참조를 포인터로 사용하고 T. –

+0

에 대한 참조로 사용할 수 있습니다. 'AdaptedGaussian이 가능한 모든 가우시안 클래스'의 '포장'또는 ' (a) 기존 인스턴스를 래핑하는 것은 필수 사항이 아니므로 (b) 포인터의 사용은 솔루션의 '포장'솔루션이 아니라 '솔루션의 인스턴스'를 목표로했기 때문에 구현 세부 사항이라고 생각했습니다. 문제의 중요한 요구 사항을 놓쳤습니까? –