2017-03-07 1 views
2

개체 조각이 위험한시기/이유에 대해 공부하고 있습니다.Object slicing : pass 값에 의한 Base로 파생되었습니다 - 안전하거나 위험합니까?

나는 what is safe slicing VS dangerous slicing에 관한 훌륭한 링크를 읽었습니다. 여기
내가 (대략 말하기) 요약 할 수 있습니다 무엇 : -

  • 안전 기본 유형이 (예를 들어 A) 때.
  • 위험한참조 (예 : A&) 인 경우 위험한입니다.

그것을 읽은 후, 나는 비주얼 스튜디오 + ReSharper에서 (A VS 플러그인)에 테스트 코드를 만들었습니다.
내 경우는 안전라고 생각합니다. 그러나 표시된 줄에 #1이라는 경고가 나타납니다. 내 믿음에서 모순의 방법으로

가능성이 의도하지 않은 객체 슬라이스 파생 클래스 C에서 값 초기화

class B1{ int field1=0; }; 
class B2{ int field2=0; }; 
class C: public B1,public B2{ }; 
class Test{ 
    void f(B1 b){ }        #2 
    void f2(){ 
     C c; 
     f(c); 
     //^ possibly unintended object slicing #1 
    } 
}; 

ReSharper에서 역할을합니다. 타입

  • 경고.
  • 없음 경고 타입 (B1에서 B1&로 변경 # 2) 참조인 경우.
  • 항상 경고 없음 CB1에서만 파생됩니다. (B 또는 B&)

는 그것은 테이블로 요약함으로써 수 있습니다 : - 그러나, 여기

     | #2=B1 | #2=B1& 
================================================== 
multi-inherit   | warn* | no-warn*  
-------------------------------------------------- 
inherit only from B1 | no-warn | no-warn  

내가 기대하는 것입니다 : -

     | #2=B1 | #2=B1& 
=================================================================== 
multi-inherit   |  safe* | dangerous*  
------------------------------------------------------------------- 
inherit only from B1 |  safe |  safe  

불일치가 *와 마크입니다.

개체 조각에 대해 오해가 있거나 Resharper이 잘못 되었나요?

+5

실제로 [슬라이스]는 [포인터 또는 참조] (https://stackoverflow.com/questions/15188894/why-doesnt-polyymismismwork-without-pointers-references)를 사용하면 값으로 지정할 때만 문제가 될 수 있습니다. 개체가 조각화되지 않고 올바르게 다형 적으로 동작합니다. – CoryKramer

+0

(수정 됨) 좋은 지적!너는 옳은 것 같아. 나는 이제 그것을 이해한다. 감사! – javaLover

+0

@CoryKramer 원하는 경우 솔루션으로 게시 할 수 있습니다. :) – javaLover

답변

1

ReSharper에서 역할을합니다.

경고 유형이 값이 때 그것은 올바른 방법으로 역할을

는 볼 수 있습니다. 함수 호출에

class B1{ int field1=0; }; 
class B2{ int field2=0; }; 
class C: public B1,public B2{ }; 
class Test{ 
    void f(B1 b){ } 
    void f2(){ 
     C c; 
     f(c); 
     } 
}; 

, B1에서 파생 형 C 가변 c로부터 입력 B1 가변 b 값 초기화의 복사 생성자를 실행 :

이이 코드를위한 B1 (서명이 B1(const B1& rhs); 인 경우)이 생성자에서 (자동 생성 여부와 상관없이) B1에있는 필드 만 rhs에서 복사되므로 나머지는 B2 또는 C)가 슬라이스됩니다.

유형이 참조 일 때 경고가 없습니다 (B1에서 B1로 변경 # &). 정확한

void f(B1& b){ } 

이 포인터 또는 기본 클래스 타입의 오브젝트 참조를 할당하여 주위에 전달되는 방법을 다형성 개체이다.

C가 B1에서만 파생되었지만 # 2는 아무런 경고가 표시되지 않습니다. (B 또는 B &)

그게 만 C 더 필드가 없으므로이 경우에는 슬라이스가 없기 때문이다. int n;C에 추가하면 경고가 다시 표시됩니다.

+0

'int n을 추가 해보십시오; 이상하게도,이 진술은 나에게 계몽 적이다. 그것은 내 마음을 이긴다. – javaLover

1

타입 (B1 &을 B1로 변경 # 2) 참조 아니 경고.

f가 f(B1& b) 인 경우 슬라이싱이 발생하지 않습니다. 경고는 없습니다.

C가 B1에서만 파생되었지만 # 2는 아무런 경고가 표시되지 않습니다. (B 또는 B &)

C가 B1에서만 파생되면 그 전체 상태는 기본 하위 개체 B1에 포함됩니다. 따라서 실제로 전환으로 인해 데이터가 분리되지 않습니다. 아마도 IDE는 그러한 경우 의도하지 않은 변환이 문제가되지 않을 것이라고 생각합니다.

난 당신이 개체에 대한 기본 참조를 바인딩 기본 하위 객체를 슬라이스 것이라고 가정하는 것

슬라이스 객체에 대한 오해 마십시오. 그렇지 않습니다. 슬라이스 (링크 대답에 따라)"위험한"는 객체가 참조를 통해 할당 될 때 발생 : 나의 믿음에서 모순의 방법으로

void f(B1& b){ 
    b = C{}; // the B2 portion of the argument is sliced off; 
      // only B1 portion is assigned. If b refers to a 
      // C, then ((C&)b)::B2 remains unmodified. 
      // If that was unintentional, then you were affected 
      // by the treacherousness 
} 
관련 문제