2009-02-26 5 views
5

저는 기본 클래스와 파생 클래스가 있습니다. 각 클래스에는 .h 파일과 .cpp 파일이 있습니다.dynamic_cast가 실패했습니다.

나는 다음과 같은 코드에서 파생 된 클래스에 기본 클래스 객체의 dynamic_cast는 뭐하는 거지 : 어떤 이상한 이유에서

Base::Base() 
{ 
    //do something.... 
} 
Base::~Base() 
{ 
    //do something.... 
} 
void Derived::foo() 
{ 
    Another a; 
    a.bar(this); 
} 
void Another::bar(Base* pointerToBaseObject) 
{ 
    dynamic_cast<Derived*>(pointerToBaseObject) 
} 

:

시간 파일 :

class Base 
{ 
    public: 
    Base(); 
    virtual ~Base(); 
}; 

class Derived : public Base 
{ 
    public: 
    Derived(){}; 
    void foo(); 
}; 

class Another 
{ 
    public: 
    Another(){}; 
    void bar(Base* pointerToBaseObject); 
}; 

CPP 파일을 , 캐스팅 실패 (NULL 반환). 그러나 파생 클래스의 생성자 구현을 .h에서 .cpp 파일로 이동하면 형 변환이 성공합니다.

어떻게 될 수 있습니까?

컴파일러는 Linux-SUSE의 gcc 3.1입니다. BTW,이 플랫폼에서만이 동작을 볼 수 있으며 동일한 코드가 Visual Studio에서 잘 작동합니다.

+0

어쩌면 GCC 3.1 버그의와 잘 작동? "-fdump-class-hierarchy"옵션을 시도해보고 두 클래스에 대한 vtable을 생성하는지 확인하십시오. –

답변

5

게시 된 코드는 기본 클래스에 가상 함수가있는 경우 실패하지 않아야합니다 (litb가 지정된 것처럼).

하지만 모든 현재 컴파일러는 "기본 클래스가 다형성이 아닙니다."라는 오류를 생성한다고 생각합니다. 그렇게하지 않으면 문제가되지 않을 것입니다.

내가 생각할 수있는 유일한 것은 모든 이상한 버그로 인해 모든 것이 인라인되고 vtable이 생성되지 않는다는 것입니다. 그러나 C++ 파일에 생성자를 넣으면 컴파일러가 모든 것을 인라인하지 않기로 결정하여 vtable 생성을 시작하여 캐스트가 작동하도록합니다.

는 그러나 이것은 매우 야생 추측, 그리고 난 당신이 명확한 대답을 원하는 경우 (?)를 컴파일러가 이러한 실수를했을

을 생각하는 더 많은 코드를 게시하지 않습니다. 그리고 컴파일러/플랫폼이 사용되었습니다.

편집 : 업데이트 된 코드

난 당신이 적어도 자료에서 파생 도출해야한다고 생각보고) (I 그 오타의 생각을) 이

그러나 코드를보고 난 후에, 유일한 것은 내가 생각할 수있는

gcc (잘못)가 모든 것을 인라인하고 파생 된 vtable을 생성하지 않는다는 것입니다. 가치가있는 부분에 대해서는 gcc로 컴파일 된 상태로 실행됩니다.

3.1 현재 7 살이 넘었습니다 ... 업그레이드 할 가능성이 있다면 제가 갈 것입니다.

7

자료실에 가상 기능이 있습니까? 그렇지 않으면 작동하지 않습니다. 그 밖의 것이 없다면 dtor를 가상으로 만드십시오.

다른 사람이 이미 답변을 삭제했는지 여부를 모르겠지만 다른 내용이라고 생각합니다. 기본 생성자에서 dynamic_cast를 수행하고 있습니까? 그렇다면 작동하지 않습니다. 컴파일러는 Base가 가상 함수를 호출 할 때와 비슷하게 Base의 버전을 호출하는 것과 유사한 가장 파생 된 유형이라고 생각합니다.

+0

Base에 가상 함수가 있습니다. –

3

소멸자를 가상으로 만들고 적어도 하나의 가상 메서드를 .cpp 파일에 배치합니다.

일부 컴파일러 (읽기 : gcc)는 처음으로 발생한 비 직렬 가상 메서드 본문을 찾아 가상 메서드 테이블을 저장할 위치를 결정하는 데 사용합니다..cpp 파일에 본문이있는 가상 메서드가없는 경우에는 가상 메서드 테이블이 만들어지지 않습니다.

dynamic_cast가 작동하려면 하나 이상의 가상 메서드가 있어야합니다. 동적 캐스팅은 테이블을 사용하여 유형 정보를 알아 내고 가상 메소드가없는 경우 테이블이 작성되지 않습니다.

서브 클래 싱 할 클래스가 있고 소멸자가 있거나 클래스에 소멸자가있는 클래스 인 인스턴스 변수가있는 경우 소멸자를 가상으로 만들려고합니다. 빈 몸). 그렇지 않으면 서브 클래스 인스턴스에 대해 예상 한 정리가 수행되지 않습니다.

0

Visual C++에서이 작업을 수행하고 있습니까? 난 당신이 작동하도록 컴파일러 설정에서 런타임 유형 정보 (RTTI)를 활성화해야 할 것 같아요.

내가 잘못했으면 저에게 불꽃을주지 마십시오. 내가 C++을 사용한 이후로 꽤 오래되었습니다 !!!

0

코드를 살펴보면 어떤 상속도 표시되지 않습니다. 그 일을 잊었 니? 파생 된 파생 아무것도에서 파생되지 않습니다.

0

게시 한 코드에서 Derived는 Base에서 파생되지 않았습니다.

편집 :가 참고로, 수정 된 코드는 g ++ 3.4.5

관련 문제