2011-08-26 4 views
3

로 변환 : 그런데 왜 C++ 스트로브 스트 룹의 책dynamic_cast는 의심 : 나는 코드를 다음은 컴파일 오류가 있습니다 것을 알고 보호 기본 클래스

class A{ public : virtual void name(){cout<<typeid(this).name()<<endl;}; }; 
class B:protected A{public : virtual void name(){cout<<typeid(this).name()<<endl;};}; 
void foo(B* b) 
{ 
    A * a = dynamic_cast<A*>(b); //Error : 'A' is an inaccessible base of 'B'  
    return; 
} 

을 (15.4.1)는 그가

class BB_ival_slider:public Ival_slider,protected BBslider{ //... 
}; 
void f(BB_ival_slider*p) 
{ 
// ok 
BBslider* pbb2 = dynamic_cast<BBslider*>(p); // ok: pbb2 becomes 0 
} 
를 기록

라인이 컴파일 오류가 아니어야합니까? 그래서 내 gcc는 컴파일 오류 또는 생각할 수없는, stroustrup 오타 또는 가장 그럴듯하게 뭔가를 놓친 뭔가를 놓친 뭔가를 놓친 ......... 플래그를 잘못 잘못되었습니다.

+0

재미있는 질문 - 기본이 가상이고 하위 하위 클래스가 '공개 가상'을 통해 동일한 기본에서 파생되는 경우에도 실패합니다 ... 컴파일러가 이것을 거부 할 수있는 이유에 대한 C++ 표준 인용문을보고 싶습니다. – bdonlan

+0

나는 게으르다. :(보통 나는 표준으로 Stroustrup의 말을 따릅니다. :) 그런 활발한 언어에 대해 세상을 가장 건조하고 지루한 표준 보고서를 열 필요가 있다고 생각합니다. –

+3

@bdonlan : 5.2.7 para 5에서는'dynamic_cast (pointer_to_class_D)에 대해서''B'는 ** 접근 가능한 ** 모호하지 않은'D'의 기본 클래스 "(emphasis mine)가 될 것이라고 말했습니다. –

답변

2

15.4.1에서 실제 인용은 다음과 같습니다

class BB_ival_slider : public Ival_slider, protected BBslider { 
    // ... 
}; 

void f(BB_ival_slider* p) 
{ 
    Ival_slider* pi1 = p; // ok 
    Ival_slider* pi2 = dynamic_cast<Ival_slider*>(p); // ok 
    BBslider* pbb1 = p; // error: BBslider is a protected base 
    BBslider* pbb2 = dynamic_cast<BBslider*>(p); // ok: pbb2 becomes 0 
} 

이것은 흥미롭지 않습니다. 그러나 dynamic_cast이 개인 및 보호 된 기본 클래스의 우발적 인 위반을 허용하지 않는다는 것을 안심할 수 있습니다.

그래서 코드를 설명하는 텍스트가 올 것으로 보인다,하지만 잘못된 이유 - dynamic_cast개인 보호 기본 클래스의 보호 실수로 위반을 허용하지만 않는 경우에만 그것을 사용하기 때문에 형식이 잘못되어 컴파일러 오류가 발생합니다. 사용하지 않으면 null 포인터가 생성됩니다. 그리고 물론 텍스트가 설명하는 코드는 입니다.입니다.

실수가 발생합니다. 책의 4 판에서 수정 될 수도 있습니다. : -]

(또한, BB_ival_sliderf을 선언한다면, friend 수 있습니다 다음 코드 것이다 아마이 friend 선언은 이전 장에서 암시했지만, 그렇게하지 책에 설명 된대로 동작합니다. 한 번에 다른 방법을 확인하기 위해주의 깊게 읽어야 할 시간이 있습니다.)

+0

와우, 나는 그 책에서 그 내용을 베끼기 위해 당신이 무엇을 사용했는지 알고 싶다. 너 뭐야? PDF 또는 일부 전자 책? –

+0

@Ajeet : 내 하드 카피를보고 짧았 기 때문에 타이핑했습니다. 전자 책이있는 경우 챕터에서 '친구'라는 단어를 검색하고 마지막 단락에서 제기 된 질문에 답할 수 있습니다. ; -] – ildjarn

+0

멋지다, 당신은 제 타입이고, Stroustrup을 그의 데스크탑에서 손에 닿을 수있게 유지합니까? –

0

아마 그 코드를 테스트했습니다. 많은 저자들이 테스트되지 않은 코드를 책에 집어 넣었습니다. 테스트를 해본 결과, 모든 컴파일러가 평등하게 생성되는 것은 아닙니다. g ++은 error: 'BBslider' is an inaccessible base of 'BB_ival_slider'으로 실패합니다. clang은 error: cannot cast 'BB_ival_slider' to its protected base class 'BBslider'으로 실패합니다. 다른 컴파일러 : 누가 알겠습니까? 필자가 알고있는 모든 컴파일러에는 표준 준수 문제가 있습니다.

+1

음, 우리는 여기 stroastrup에 대해 이야기하고 있습니다 .... 표준은 그의 마음을 반영합니다. 그 반대도 마찬가지입니다. : P –

+0

괜찮습니까? Q : –

0

나는 내가 어떤 건설적인 증거를 찾는 아니에요이라면 난 그냥 내가 생각하는 컴파일러의 내장을 유출하도록 허용 해달라고

(즉 :(무서운 소리)

"스트로브 스트 룹은 잘못"말할지도 모른다 생각 .. 클래스 (정의 된 표준에 의해) 기꺼이 내부가 칼을 넣어하지 않는 한 (악한 포인터 동작은)

+0

악의적 인 포인터 조작으로 악의적 인 C 스타일의 캐스팅을 의미한다고 가정합니다. 그리고 네, C 스타일의 캐스트는 파생 클래스 포인터를 기본 클래스 포인터로 변환 할 수 있습니다. "* 기본 클래스 유형에 액세스 할 수없는 경우에도 *"(5.4 para 7). 이 악의적 인 조작의 결과는 널 포인터가 아닙니다. –

+0

@David 예, 예. 그런 종류의 c-style 흑 마법에는 치료법이 없습니다. :) 누군가가 그것을 사용했다면, 그것을 "캐스팅"한 사람 만이 그것을 신뢰성있게 실행 취소 할 수 있습니다. hehehe –