2012-02-10 4 views
7

다음 예제에서 명시 적 인터페이스 (사례 1, 추상 클래스의 포인터)를 사용하는 암시 적 인터페이스 (사례 2 및 3; 템플릿) 사용의 장단점은 무엇입니까? 변경되지 않습니다암시 적 대 명시적인 인터페이스

코드 :

class CoolClass 
{ 
public: 
    virtual void doSomethingCool() = 0; 
    virtual void worthless() = 0; 
}; 

class CoolA : public CoolClass 
{ 
public: 
    virtual void doSomethingCool() 
    { /* Do cool stuff that an A would do */ } 

    virtual void worthless() 
    { /* Worthless, but must be implemented */ } 
}; 

class CoolB : public CoolClass 
{ 
public: 
    virtual void doSomethingCool() 
    { /* Do cool stuff that a B would do */ } 

    virtual void worthless() 
    { /* Worthless, but must be implemented */ } 
}; 

사례 1 :

class CoolClassUser 
{ 
public: 
    void useCoolClass(CoolClass * coolClass) 
    { coolClass.doSomethingCool(); } 
}; 

int main() 
{ 
    CoolClass * c1 = new CoolA; 
    CoolClass * c2 = new CoolB; 

    CoolClassUser user; 
    user.useCoolClass(c1); 
    user.useCoolClass(c2); 

    return 0; 
} 

사례 2 : 명시 적 인터페이스를 제공하는 기본 클래스 포인터를 취 비 템플릿 A 급 템플릿 유형이 암시 적 인터페이스를 제공하는 템플릿 유형의 클래스 :

template <typename T> 
class CoolClassUser 
{ 
public: 
    void useCoolClass(T * coolClass) 
    { coolClass->doSomethingCool(); } 
}; 

int main() 
{ 
    CoolClass * c1 = new CoolA; 
    CoolClass * c2 = new CoolB; 

    CoolClassUser<CoolClass> user; 
    user.useCoolClass(c1); 
    user.useCoolClass(c2); 

    return 0; 
} 

사례 3 : 템플릿이있는 템플릿 기반 클래스

class RandomClass 
{ 
public: 
    void doSomethingCool() 
    { /* Do cool stuff that a RandomClass would do */ } 

    // I don't have to implement worthless()! Na na na na na! 
}; 

template <typename T> 
class CoolClassUser 
{ 
public: 
    void useCoolClass(T * coolClass) 
    { coolClass->doSomethingCool(); } 
}; 

int main() 
{ 
    RandomClass * c1 = new RandomClass; 
    RandomClass * c2 = new RandomClass; 

    CoolClassUser<RandomClass> user; 
    user.useCoolClass(c1); 
    user.useCoolClass(c2); 

    return 0; 
} 

사례 1은 객체가 useCoolClass (에에 전달되는 것을 요구한다)이 CoolClass의 자식 (그리고 쓸모없는 을 구현 (: 식사 유형은하지 CoolClass에서 파생 암시 적 인터페이스 (이 시간을 제공합니다)). 반면에 케이스 2와 3은 클래스를 취합니다.이 클래스에는 doSomethingCool() 함수가 있습니다. 코드의 사용자가 CoolClass 항상 좋은 서브 클래스 했다 경우 CoolClassUser 항상 CoolClass의 구현을 기대 될 수 있기 때문에

후 케이스 1, 직관적 인 의미가 있습니다. 그러나이 코드는 API 프레임 워크의 일부로 가정하므로 사용자가 CoolClass의 하위 클래스를 만들 것인지 아니면 doSomethingCool() 함수가있는 자체 클래스를 롤링할지 예측할 수 없습니다.

일부 관련 게시물 :

https://stackoverflow.com/a/7264550/635125

https://stackoverflow.com/a/7264689/635125

https://stackoverflow.com/a/8009872/635125

+0

사례 1과 사례 2가 컴파일되지 않습니다. 포인터 초기화가 잘못되었습니다. – Novelocrat

+0

@Novelocrat가 수정되었습니다. –

답변

3

당신이 경우 1 선호 수없는 이유에 대한 내 마음에 와서 몇 가지 고려 사항 :

  • 하는 경우를 CoolClass은 순수한 인터페이스가 아니므로 구현의 일부도 상속됩니다 (사례 2/3에도 제공 할 수 있습니다. 예 : 기본 클래스의 형태로);
  • CoolClassUser을 헤더가 아닌 바이너리로 구현해야하는 이유가 있다면 (이는 보호뿐만 아니라 코드 크기, 리소스 제어, 중앙 집중식 오류 처리 등일 수도 있음);
  • 포인터를 저장하고 나중에 사용하려는 경우 케이스 1도 더 좋을 것입니다. (a) 모든 컨테이너를 같은 컨테이너에 보관하는 것이 더 쉬우 며 (b) 실제 데이터 유형을 다음과 같이 저장해야합니다. 글쎄, 케이스 2/3의 경우 마음에 떠오르는 솔루션은 템플릿 래퍼 (wrapper)의 도움으로 "명시 적"인터페이스 (예 : 케이스 1)로 변환하는 것입니다.케이스 2/3보다 더 낫다 할 이유

이유 :

  • 나중에 worthless() 지금 가치가 어떤 것을 결정하고 그것을 사용하기 시작하면, 사례 2에서 당신은 컴파일시 클래스에 대한 오류를 얻을 것이다 구현되지 않은 곳입니다. 사례 1에서 운이 좋다면 런타임 오류를 제외하고 실제 기능에 대해 이러한 기능을 구현하도록 상기시켜주는 기능은 없습니다.
  • 코드 크기가 커지더라도 Case2/3의 성능이 약간 더 좋을 수 있습니다.

경우에 따라 사용자 또는 사용자의 개인 취향에 달려있는 경우도 있습니다.

1

# 2 및 # 3의 경우 템플릿 매개 변수에 따라 달라 지므로 호출시 코더가 템플릿 인수를 올바른 유형으로 올바르게 인스턴스화해야합니다. 함수가 사용되는 방법에 따라 사용자 주위에 전달되는 객체의 유형에 대해 걱정할 필요없이 사용자를위한 추상적 인 인터페이스를 만들려는 몇 가지 문제가 발생할 수 있습니다. 즉, "핸들"또는 일부 하나의 API 함수에서 다른 API 함수로 객체를 전달하기 위해 다형성을 사용하는 파생 객체에 대한 다른 포인터. 예를 들어 : 그들은 단지 그것을 설명하는 알 필요가 ...

이제
class abstract_base_class; 

abtract_base_class* get_handle(); 
void do_something_with_handle(abstract_base_class* handle); 
void do_something_else_with_handle(abstract_base_class* handle); 
//... more API functions 

, 당신의 API 프레임 워크는 코드의 사용자에게 다시 객체를 전달할 수 있으며, 해당 개체가 무엇인지 알 필요가 없습니다 어떤 유형의 인터페이스입니다. 물론 헤더 어딘가에 공개적으로 공개 할 수 있습니다. 그러나 그들은 당신이 그들에게 돌아간 대상의 "내장"에 대해 아무 것도 알 필요가 없습니다. 구현을 제어하는 ​​파생 된 유형에 대한 포인터를 제공 할 수 있습니다. API에서 가장 일반적인 함수 유형에 대한 템플릿 만 제공하면됩니다. 그렇지 않은 경우에만 abstract_base_class*을 취하도록 고안된 함수의 템플릿을 인스턴스화하지 않아도 사용자가 입력 할 수있는 더 많은 상용구 코드가 작성됩니다.