2012-02-15 3 views
0

저는 현재 C++ 프로젝트에서 작업 중이며 현재 디자인 문제에 직면 해 있습니다. 누군가 제안 할 수 있으면 감사하겠습니다. 기본적으로 기본 클래스는 Base이고, 하위 클래스는 Derived입니다. Class Derived는 Base 클래스가 할 수없는 것을 할 수 있습니다.dynamic_cast에 알맞은 대안이 있습니까

class Base 
{ 
public: 
    virtual bool IsCapableOfDoingA() {return false;} 
} 

class Derived: public Base 
{ 
public: 
    bool IsCapableOfDoingA() {return true;} 
    void DoA(); 
} 

다른 클래스에서는 Base 클래스 유형의 포인터가 있습니다.

void functionA(Base *pBase) 
{ 
    if (pBase && pBase->IsCapableOfDoingA()) 
    { 
     Derived *pDerived = static_cast<Derived*>(pBase); 
     pDerived->DoA(); 
    } 

} 
+1

처음에는 동적 다형성을 필요로하는'Base'와'Derived'로 무엇을하고 있습니까? 컨텍스트가 없으면이 질문에 대답 할 방법이 없습니다. – ildjarn

+0

질문에'dynamic_cast'에 대한 대안을 물어 보았습니다.하지만 그게 잘못된 것입니까? – hvd

+0

더 많은 문맥없이 대답하는 것은 불가능합니다. 그러나 예상했던 것처럼 멤버 함수가 무엇인지 쿼리해야하는 상황에 있다면 설계를 거의 재검토해야합니다. –

답변

4

일반적인 방법은 기본 클래스에 함수를 추가하는 것입니다. 당신의 디자인에

virtual void DoA() { throw std::runtime_error("Not implemented"); } 
+0

평소와 다름 없다고 생각합니다. –

+0

의존 - 아무 것도하지 않는 것이 합리적이고 공통적 인 경우,'virtual void DoA() {}'를 작성합니다. 질문은'else' 브랜치에'throw '를 포함하지 않습니다. – MSalters

2

, 그것은 DoA이 어떤 종류의 성공 코드를 반환하는 괜찮아? IsCapableOfDoingADoA으로 대체하고 기본 버전이 false (또는 다른 적절한 오류 코드) 만 반환하도록 할 수 있습니다. A을 수행 할 수있는 하위 오브젝트는 적절한 구현으로이 기능을 대체 할 수 있습니다.

당신이 맞아요. dynamic_cast은 종종 디자인 냄새입니다. 좀 더 많은 맥락에서 우리는 더 나은 대답을 제공 할 수있을 것입니다. 제 첫 번째 생각은 다형성으로 수행 할 수없는 일에 대해 Base을 물어 보는 경우 실제로 Derived IS-A Base을 확인하는 것입니다.

+0

Base는 A를 수행 할 수 없기 때문에 Base가 false를 반환하는 것이 좋습니다. 그러나 Base는 A를 수행 할 수 없으므로 Base에이 인터페이스를 제공하는 것이 실제로 가능한지를 판단하고 있습니다. IIRC, 책 "Effect C++"에서 논의 된 디자인 문제입니다. 저자는 새가 날 수 있는지 없는지를 보여주었습니다. 따라서 Bird 클래스에는 fly()를 제공하지 않는 것이 좋지만 fly() 멤버 메서드가있는 FlyableBird 하위 클래스를 파생시키는 것이 좋습니다. –

+0

네, _ Effective C++ _ 3 판의 # 32 아이템입니다. Scott은 제안 사항을 제시하지만 ([Mark 's answer] (http://stackoverflow.com/a/9300547/46821)) 절대적인 정답은 없습니다. –

1

dynamic_cast는 객체에 적절한 유형이 없으면 NULL을 반환합니다 (기본 클래스가 적어도 하나의 가상 메서드를 정의한다고 가정하면 일반적으로 기본 클래스의 소멸자를 가상으로 만들어야합니다). pBase 유형은 유래가없는 경우

void functionA(Base *pBase) 
{ 
    if (Derived *pDerived = dynamic_cast<Derived*>(pBase)) { 
     pDerived->DoA(); 
    }  
} 

, 다음 pDerived는 0 (거짓)입니다, 그래서 if 문의 몸 건너 뜁니다 : 그래서 당신은 다음과 같은 관용구를 사용할 수 있습니다.

0

다른 아이디어가 있습니다. 향상된 기능을 인터페이스로 분리하고 인터페이스 포인터를 리턴하는 메소드를 가질 수 있습니다.

class InterfaceA 
{ 
public: 
    virtual ~InterfaceA() {} 
    virtual void DoA() = 0; 
}; 

class Base 
{ 
public: 
    virtual InterfaceA* GetAInterface() {return NULL;} 
}; 

class Derived: public Base, InterfaceA 
{ 
public: 
    InterfaceA* GetAInterface() {return this;} 
    void DoA(); 
}; 

void functionA(Base *pBase) 
{ 
    InterfaceA* pA = pBase ? pBase->GetAInterface() : NULL; 
    if (pA) 
     pA->DoA(); 
} 
+0

제안에 감사하는 표입니다. 솔루션에 static_cast가 필요하지 않습니다. –