2011-09-17 5 views
3

다음과 같은 추상 클래스를 생각해 보자.동적 캐스트 또는 함수 오버로드

class Abstract { 
public: 
    // ... 

    virtual bool operator==(const Abstract& rhs) const = 0; 

    // ... 
}; 

이제이 추상 클래스에서 파생 클래스를 여러 개 생성한다고 가정 해 보겠습니다. 그러나 각 클래스는 자체 알고리즘 유형과 비교할 때 다른 알고리즘을 사용하고 다른 파생 클래스와 비교할 때는 일반 알고리즘을 사용합니다. 다음 두 가지 옵션 중에서 더 효율적이고 효율적인 옵션이 있습니까?

옵션 A :

class Derived : public Abstract { 
public: 
    // ... 

    bool operator==(const Abstract& rhs) const { 
     // Code for comparing to any of the other derived classes 
    } 

    bool operator==(const Derived& rhs) const { 
     // Code for comparing to myself 
    } 

    // ... 
}; 

옵션 B :

class Derived : public Abstract { 
public: 
    // ... 

    bool operator==(const Abstract& rhs) const { 
     const Derived* tmp = dynamic_cast<const Derived*>(&rhs); 
     if (tmp) { 
      // Code for comparing to myself 
     } 
     else { 
      // Code for comparing to any of the other derived class 
     } 
    } 
}; 

C++ typecasting이 나에게 상대적으로 신비로운 주제이기 때문에 이러한 옵션의 장점과 단점에 대해 궁금합니다. . 또한 어떤 솔루션이 더 "표준"이며 두 번째 솔루션이 성능에 어떤 영향을 미칩니 까?

아마도 세 번째 솔루션이 있습니까? 특히 파생 클래스가 많은 경우 각각 다른 파생 클래스에 대해 자체 비교 알고리즘이 필요합니까?

답변

1

나는 옵션 == 연산자가 동적 유형의 인수를 사용하기를 기대하고 있다면 옵션 B를 찾고 있다고 생각합니다.

class base 
{ 
public: 
    virtual bool operator ==(const base& other) = 0; 
}; 

class derived : public base 
{ 
public: 
    bool operator ==(const base& other) { return false; } 
    bool operator ==(const derived& other) { return true; } 
}; 


int main() 
{ 
    base* a = new derived; 
    base* b = new derived; 
    std::cout << (*a == *b) << std::endl; 
} 

이 인쇄 : 예를 들어

0 

그래서 오퍼레이터 == (CONST & 다른 염기) 호출되는 실제 동적 타입이더라도 산출했다.

+0

알겠습니다. 이 예제는 제가 수행 한 일종의 것입니다.비록 옵션 A가 내 특정 필요에 더 적합하다고 생각하지만, 객체가 올바른 유형이 아니더라도 사용할 알고리즘을 제어 할 수 있기를 원하기 때문에이 예제는 어떻게 할 수 있는지 정확하게 보여줍니다. 고맙습니다! – Zeenobit

2

두 가지 방법은 상황에 따라 다릅니다. 옵션 A의 경우 정적 유형 rhs은 호출 할 함수를 결정하는 데 사용되며, 옵션 B의 경우 동적 유형이 사용됩니다.

그래서 프로그램이 인수의 "실제"유형에 대한 행동 기반을 선택하게하려면 두 번째 옵션을 선택해야한다고 생각합니다. 유형을 컴파일 할 때 알 수 있으면 더 나은 성능을 제공하므로 옵션 A를 사용해야합니다.

+0

그래서'dynamic_cast'는 실제로 상대적으로 높은 성능 비용을 갖고 있습니까? – Zeenobit

+0

@teedayf, * 상대적으로 높음 *은 삼가면서 말하는 것입니다. 좋습니다. 좀 더 심각하게 말하자면, 성능에 치명적인 무언가에'dynamic_cast'를 사용하지 않는 한 걱정할 필요가 없습니다. – Marlon

1

실제로는 두 번 발송을 구현하는 techiniques 중 하나를 사용하여 세 번째 방법으로 수행 할 수 있습니다. 이 접근법은 "보다 효과적인 C++"31 항에 자세히 설명되어 있습니다. 여기에 작은 예입니다 :

#include <iostream> 

class Derived1; 
class Derived2; 

class Base 
{ 
public: 
    virtual bool operator==(Base& other) = 0; 
    virtual bool compare(Base& other) {return false;} 
    virtual bool compare(Derived1& other) {return false;} 
    virtual bool compare(Derived2& other) {return false;} 
}; 

class Derived1 : public Base 
{ 
public: 
    virtual bool operator==(Base& other) {return other.compare(*this);} 

    virtual bool compare(Base& other) {return false;} 
    virtual bool compare(Derived1& other) {return true;} 
}; 

class Derived2 : public Base 
{ 
public: 
    virtual bool operator==(Base& other) {return other.compare(*this);} 

    virtual bool compare(Base& other) {return false;} 
    virtual bool compare(Derived2& other) {return true;} 
}; 

int main() 
{ 
    Base *a = new Derived1; 
    Base *b = new Derived1; 
    Base *c = new Derived2; 

    std::cout << (*a == *b) << std::endl; 
    std::cout << (*a == *c) << std::endl; 
    return 0; 
} 

출력 :

1 
0 
0

불행하게도 C++의 동적 유형의 정보를 기반으로 호출 할 수있는 현재의 기능을 선택하는 것이 더 multimethods이 없습니다. 행동을 구현하려면 이중 발송, 방문자 패턴 또는 다른 트릭이 필요합니다.