2012-03-28 3 views
18

동적/정적 다형성은 애플리케이션 설계 및 요구 사항에 따라 달라진다는 것을 알고 있습니다. 그러나 가능하다면 항상 정적 인 다형성을 동적으로 선택하는 것이 좋습니다?Dyamic 대 C++의 정적 다형성 : 어느 것이 더 좋습니까?

  1. 하는 CRTP를 사용하여 정적 다형성을 구현 : 특히, 나는에 대해 조언을하는 것 둘, 내 응용 프로그램에 다음이 디자인 선택을 볼 수있는 vtable을 조회 오버 헤드를 여전히 템플릿 형태의 인터페이스를 제공하면서 기본 클래스. 그러나, 유해

  2. 동적 다형성이고 올바른 클래스/방법 액세스로 전환 static_cast 많이 사용 접근/변경자 추천에도 단순 기능 룩업 선정 연관, 인터페이스 (순수 가상 클래스)를 구현을

내 응용 프로그램은 매우 시간이 중요하므로 정적 다형성을 선호합니다. 그러나 너무 많은 static_cast를 사용하면 디자인이 좋지 않다는 것을 알 수 있어야하고 대기 시간을 발생시키지 않고이를 방지하는 방법을 알아야합니다.

편집 : 통찰력에 감사드립니다. 구체적인 경우를 생각해보십시오. 이들 중 어느 것이 더 나은 접근 방법입니까?

class IMessage_Type_1 
{ 
    virtual long getQuantity() =0; 
... 
} 
class Message_Type_1_Impl: public IMessage_Type_1 
{ 
    long getQuantity() { return _qty;} 
... 
} 

또는

이 각 클래스의 여러 뮤 테이터/접근이, 나는 내 응용 프로그램의 인터페이스를 지정해야 않는 것이
template <class T> 
class TMessage_Type_1 
{ 
    long getQuantity() { return static_cast<T*>(this)->getQuantity(); } 
... 
} 
class Message_Type_1_Impl: public TMessage_Type_1<Message_Type_1_Impl> 
{ 
    long getQuantity() { return _qty; } 
... 
} 

참고. 정적 다형성에서는 메시지 유형을 얻기 위해 한 번만 전환합니다. 그러나 동적 다형성에서는 각 메소드 호출에 가상 함수를 사용하고 있습니다. 정적 폴리를 사용하는 경우가 아닙니까? 나는 CRTP의 static_cast가 꽤 안전하고 성능상의 불이익 (컴파일 타임 바운드)이 없다고 믿는다.

+4

스위치 케이스 구조는 vtable을 사용하는 것과 동일한 복잡성을 갖습니다. – user877329

+0

정적 인 다형성을 사용할 때 왜 static_cast 및 스위치로 끝날 것이라고 생각하는지 모르겠습니다. 몇 가지 예제 코드를 보여줄 수 있습니까? –

+1

@MichaelAnderson : 동적 다형성을 필요로하는 상황에서 정적 다형성을 사용하려고하면이 문제가 발생합니다. 이 경우 역동적 인 다형성을 재발 명하기보다는 사용하는 것이 거의 확실합니다. –

답변

8

스위치는 테이블에 의해 룩업 된 주소로의 점프가되는 - 이후 최적화 된 점프 시퀀스 이상일 수 없습니다. 마치 가상 함수 호출과 같습니다.

유형에 따라 점프해야하는 경우 먼저 유형을 선택해야합니다. 선택 사항을 컴파일 타임에 수행 할 수없는 경우 (본질적으로 입력에 의존하기 때문에) 반드시 & 점프를 선택하십시오. 구문 도구을 선택하면 성능이 변경되지 않으므로 최적화 할 수 있습니다.

실제로 당신은 인데, v 테이블을 재발 명합니다.

+0

스위치 케이스가 기본적으로 vtable이라는 것에 동의합니다. 그러나 동적 다형성에서는 모든 메소드에 가상을 사용하지만 static에서는 유도 타입을 얻기 위해 스위치와 캐스트를 한 번 수행해야합니다. 간접적 인 것은 없습니다. 질문에 예제를 추가했습니다. 이것을 구현하는 더 좋은 방법이 있습니까? – vid

+0

@vid : 호출자가 파생 된 유형에 대해 알도록 허용 된 경우, 다형성의 목적은 무엇입니까? 이 경우 호출자는 추상화, 인터페이스 등이없이 파생 클래스와 직접 상호 작용할 수 있습니다. 여기에는 다형성과 상속이 모두 중복되어 있습니다. 호출자가 파생 된 유형, 을 알 수없는 경우 기본 유형의 각 호출에서 유형 캐스팅 및 메소드 디스 패칭이 수행되어야합니다. vtable은 이러한 디스 패칭에 최적의 솔루션입니다. CRPT는 기본 클래스에서 파생 클래스로 호출을 최적화하는 데 적합한 도구입니다 ( – user396672

+0

). 알았어, 고마워. 내가하려는 것은 CRTP를 사용하여 인터페이스를 지정하는 것이 었습니다. 따라서 다른 개발자가 라이브러리를 확장하려고 할 때 CRTP를 사용하여 기본 클래스를 상속하고 메소드를 구현하지 못하면 컴파일 오류가 발생합니다. 순수 가상 기본 클래스와 동일한 논리이지만 vtable 오버 헤드가 없습니다. 내가 이것을 어떻게 적절하게 구현하는지 생각할 수있는 관용구가 있습니까? – vid

6

순전히 템플릿 기반 다형성과 관련된 디자인 문제가 있습니다. 찾고있는 가상 기본 클래스는 파생 된 클래스에서 기대할 수있는 좋은 아이디어를 제공하지만, 템플릿이 많은 디자인에서는 훨씬 더 어려워집니다. 하나는 부스트 라이브러리 중 하나를 사용하는 동안 구문 오류를 도입함으로써 쉽게 증명할 수 있습니다.

반면에 가상 기능을 사용할 때 성능 문제가 발생할 수 있습니다. 이것이 문제가 될 것이라는 교정은 훨씬 더 어렵습니다.

이건 비 질문입니다. 별도로 명시 될 때까지 가상 기능을 고수하십시오. 가상 함수 호출은 대부분의 사람들이 생각하는 것보다 훨씬 빠릅니다 (동적 링크 라이브러리에서 함수를 호출하면 간접적 인 계층이 추가됩니다. 아무도 그것에 대해 생각하지 않는 것 같습니다).

코드를 읽기 쉽도록 (일반 알고리즘) 작성하면 템플리트 설계 만 고려하고 가상 함수 (숫자 알고리즘)에서는 느린 것으로 알려진 몇 가지 사례 중 하나를 사용하거나 이미 성능으로 식별했습니다 병목.

+0

감사합니다. @ebo.내 응용 프로그램에서 병목 현상으로 가상 기능을 식별하지 않고 오버 헤드를 명확하게 만들기 위해 질문을 편집했습니다. – vid

14

정적 및 동적 다형성은 서로 다른 문제를 해결하기 위해 설계되었으므로 둘 다 적합한 경우는 거의 없습니다. 이러한 경우 에서 동적 다형성은 더 유연하고 더 쉽게 디자인을 관리 할 수 ​​있습니다. 그러나 대부분의 경우, 선택은 다른 이유로 명백합니다.

두 가지의 대략적인 분류 : 가상 함수는 공통 인터페이스에 대해 다른 구현을 허용합니다. 템플릿을 사용하면 공통 구현을 위해 서로 다른 인터페이스를 사용할 수 있습니다.

+0

'가상 함수는 공통 인터페이스에 대해 다른 구현을 허용합니다. 템플릿은 공통된 구현을 위해 서로 다른 인터페이스를 허용합니다. '이것은 실제로 의미가 없습니다. 정적 다형성은 실제로 두 개의 서로 다른 클래스가 고유 한 구현을 만들도록 허용하지만 메소드는 동일한 이름을 가지며 두 경우 모두 기본 클래스에서 호출됩니다. – johnbakers

+1

@Fellowshee 가장 일반적으로 사용되는 템플릿 클래스는 인터페이스가 다르지만 각 구현 유형에 대해 동일한 구현을 제공합니다. 'std :: vector '은'push_back (double)'함수를 제공하는데,'std :: vector '은'push_back (int)'을 제공합니다. 다른 인터페이스; 동일한 구현. 가상'push_back (double)'로부터의 상속은 다른 구현을 가능하게하지만, 다른 인터페이스는 허용하지 않을 것이다. –

1

정적 메서드는 호출 된 메서드가 컴파일러에 의해 인라인 될 수있는 경우 중요한 이점을 제공 할 수 있습니다. 예를 들어, 가상 방법은 다음과 같습니다 경우 :

protected: 
virtual bool is_my_class_fast_enough() override {return true;} 

다음 정적 polimophism이 선호하는 방법 (그렇지 않으면, 방법은 정직과 거짓 :)를 반환해야해야한다.

"True"가상 호출 (대부분의 경우)은 인라인 될 수 없습니다. (예 : VTABLE 호출에 추가 간접 등)

다른 차이는 무시할 수 있습니다

그러나 [편집] 만약 당신이 호출자가 알지 못하는 경우는 런타임 다형성 을 (필요 정말메서드의 구현 및 그러므로, 메서드는 호출자 측에 인라인 될 수 없습니다) 다음 (에밀리오 Garavaglia 언급 한대로) vtable, 그냥 그것을 재발견하지 마십시오.

관련 문제