2008-10-28 2 views
5

가정 해보니 자료 클래스와 여러 유도 된 클래스가 있습니다. 다음과 같이 작성할 필요없이 파생 클래스 중 하나에 객체를 캐스트 할 수있는 방법이 있습니까?C++ 캐스팅을 프로그래밍 방식으로 : 수행 할 수 있습니까?


string typename = typeid(*object).name(); 
if(typename == "Derived1") { 
    Derived1 *d1 = static_cast< Derived1*>(object); 
} 
else if(typename == "Derived2") { 
    Derived2 *d2 = static_cast < Derived2*>(object); 
} 
... 
else { 
    ... 
} 

답변

22

하지 마십시오.

다형성에 대한 내용을 읽으십시오. 거의 모든 "다이내믹 캐스트"상황은 구현하기 위해 고군분투하는 다형성의 예입니다.

동적 캐스트에서 어떤 결정을 내려야할지 이미 결정되었습니다. 실제 작업을 서브 클래스에 위임하십시오.

예제에서 가장 중요한 부분을 생략했습니다. 유용한 다형성 작업.

string typename = typeid(*object).name(); 
if(typename == "Derived1") { 
    Derived1 *d1 = static_cast< Derived1*>(object); 
    d1->doSomethingUseful(); 
} 
else if(typename == "Derived2") { 
    Derived2 *d2 = static_cast < Derived2*>(object); 
    d2->doSomethingUseful(); 
} 
... 
else { 
    ... 
} 

모든 하위 클래스가 doSomethingUseful을 구현하면이 모든 것이 훨씬 간단합니다. 그리고 다형성.

object->doSomethingUseful(); 
+0

이것은 세부적인 내용이지만 언급하고 싶습니다. 당신은 d1보다는 d1->와 d2->를 의미합니다. 및 d2. ,권리? 포인터 타입은 화살표 연산자를 사용하여 멤버 함수에 도달하기 때문에. :) –

3

일반적으로 이것은 잘못된 설계의 표시입니다. 왜 이럴 필요가 있니? 이것이 필요하지 않도록 재 설계하는 것이 가능할 수도 있습니다.

1

name()의 정확한 형식이 지정되지 않았으므로 예제가 포트되지 않습니다. 당신은 dynamic_cast의 계승을 시도 할 수 있습니다. Dynamic_cast은 잘못된 유형으로 변환하면 널 포인터를 반환합니다. 그러나 이와 같은 타입 스위치를 사용하는 경우 디자인에 문제가 있습니다.

9

dynamic_cast을 사용하고 NULL을 테스트 할 수 있지만 은 코드를 리팩토링하는 것이 좋습니다.

하위 클래스 별 처리가 필요한 경우 Template Method이 도움이 될 수 있지만 실제로 무엇을하려고하는지 모른 채 모호한 추측입니다.

2

정확히 달성하려는 것은 무엇입니까? 내 경험상 이와 같은 것은 나쁜 디자인의 징조입니다. 객체 지향 설계의 목표는 이러한 필요를 없애기 때문에 클래스 계층 구조를 재평가하십시오.

5
Derived1* d1 = dynamic_cast< Derived1* >(object); 
if (d1 == NULL) 
{ 
    Derived2* d2 = dynamic_cast< Derived2* >(object); 
    //etc 
} 

나는 '는'C#을 시뮬레이션하고 '으로'내 smartpointer 유형에 다음과 같은 방법이 있습니다

template< class Y > bool is() const throw() 
    {return !null() && dynamic_cast< Y* >(ptr) != NULL;} 
template< class Y > Y* as() const throw() 
    {return null() ? NULL : dynamic_cast< Y* >(ptr);} 
4

당신이 사용 dynamic_cast을 할 수있는, 예를 들면 :

if (Derived1* d1 = dynamic_cast<Derived1*>(object)) { 
    // object points to a Derived1 
    d1->foo(); 
} 
else if (Derived2* d2 = dynamic_cast<Derived2*>(object)) { 
    // object points to a Derived2 
    d2->bar(); 
} 
else { 
    // etc. 
} 

그러나 다른 사람들이 말했듯이 이와 같은 코드는 나쁜 디자인을 나타낼 수 있으며 일반적으로 다형성 동작을 구현하는 데 virtual functions을 사용해야합니다.

1

나는 dynamic_cast는 갈 방법입니다 생각하지만, 나는 특히이 객체가 일부 타사 모듈이 제공하는 것이 될 수있다 주조 될 수 있기 때문에 모든 가능한 조건에 대한 나쁜 설계라고 생각하지 않습니다. 객체가 애플리케이션 작성자가 알지 못하는 플러그인에 의해 생성되었다고 가정 해 봅시다. 그리고 그 특정 플러그인은 Derived1 (이전 버전 임) 유형 객체 또는 Derived2 (새 버전 임) 유형 객체를 생성 할 수 있습니다.어쩌면 플러그인 인터페이스는 특정 버전의 물건을 처리하도록 설계되지 않았을 것입니다. 객체가 생성되므로 응용 프로그램은 적절한 캐스팅/실행을 보장하기 위해 이러한 종류의 검사를 수행해야합니다. 그런 다음 안전하게 object.doSomethingUsefulThatDoesNotExistInDerived1()을 호출 할 수 있습니다.

관련 문제