의견에서 언급했듯이 일부 문제는 일반적으로 동적 디스패치가 구현되는 방식과 관련이 있습니다.
vtable 접근 방식을 가정 할 때 특정 유형은 vtable을 자체 또는 수퍼 유형으로 취급 할 수있는 vtable을 생성 할 수 있어야합니다. 단일 상속에서는 각 유형의 vtable이 즉각적인 상위 유형과 동일한 vtable 레이아웃으로 시작하고 그 뒤에 새로운 멤버가 오는 것이므로 쉽게 구현할 수 있습니다.
예.B
이 두 가지 방법
vtable_B
Slot # Method
1 B.foo
2 B.bar
그리고 B
에서 D
상속, bar
무시를 가지고 도입하는 경우 baz
:
vtable_SI_D
Slot # Method
1 B.foo
2 D.bar
3 D.baz
D
때문에이 B
의 VTABLE에서 찾은 어떤 항목이 단지 복사, foo
을 무시하지 않았다 슬롯 # 1에 대해
D
에서 B
까지의 변수를 사용하는 코드는 슬롯 # 1과 # 2 만 사용하며 모든 것이 올바르게 작동합니다.
그러나 다중 상속을 도입하면 단일 vtable을 사용할 수 없게 될 수도 있습니다. foo
및 bar
방법을 가진 C
을 소개한다고 가정 해보십시오.
vtable_MI_D_as_B
Slot # Method
1 B.foo
2 D.bar
또는 C
에 : D
이 B
로 캐스팅 할 때 이제 우리는 다른 vtable을을 사용해야합니다
vtable_MI_D_as_C
Slot # Method
1 C.foo
2 D.bar
이들은 1 모호하다. 문제는이 아무것도 캐스팅하지 않을 경우 D
의 VTABLE을 채우기 위해 노력하고있다 :
Slot # Method
1 <what goes here>
2 D.bar
3 D.baz
그래서, 당신은 올바른 것 삼각형 상속이 몇 가지 문제를 제기하고있다. 우리가 (B
또는 C
로 D
반대) D
로 D
에 대한 다른의 vtable을 사용하고 있기 때문에 그러나 우리는 는 슬롯 # 1에 대한 항목을 생략하고 불법 간단한 경우 (D.foo
를 호출 할 수 있도록 간단 수있는
vtable_MI_D
Slot # Method
2 D.bar
3 D.baz
이의 지금 A
을 소개하자하고 다시 고전적인 다이아몬드 패턴, foo
정의가 : 아무것도 더 B
들 foo
또는 오버라이드 (override) foo
)를 사용하는 등 D
의 정의에 명시되지 않습니다. 그래서 A
의 VTABLE은 다음과 같습니다
vtable_A
Slot # Method
1 A.foo
B
및 C
는 위와 같이 설명되어 있습니다. 추가 문제가 하나만있는 경우를 제외하고 위와 똑같은 방법으로 D
을 수행 할 수 있습니다. D
에 대한 vtable을 A
으로 제공해야합니다. 은 슬롯 # 1을 생략 할 수 없습니다. A
을 다루는 코드는 foo
을 호출 할 수 있어야합니다. 그리고 값이 서로 다르며 즉각적인 수퍼 유형이기 때문에 B
또는 C
의 vtable에서 항목을 복사 할 수 없습니다.
이, 저는 믿습니다, 다이아몬드 패턴이 일반적으로 사용되는 이유의 요지입니다 - 우리는 그냥 구현할 수 없기 때문에 규칙 "당신은 D
에 foo
를 호출 할 수 없습니다"과 함께 할 수.
1 그것은 또한 vtable_MI_D_as_B
및 vtable_MI_D_as_C
vtable을에 # 1과 # 2 슬롯이 여기 완전히 관련이없는 관찰 가치가있다. C
은 foo
방법에 슬롯 2를, 그 bar
방법에 슬롯 6을 사용할 수 있습니다. 동일한 이름을 가진 메소드가 반드시 "동일한"슬롯을 공유하지는 않습니다.
이것은 슬롯 # 1이 모든 유형에 걸쳐 실제로 동일한 슬롯 인 다이아몬드 상속 패턴에 대한 후반 논의와 대조됩니다.
두 번째 예제에서 모호성을 이해할 수 있을지 모르겠습니다. 여러분은'B''' foo' 메서드 또는'D'에서 재정의 할 것입니다. 그러나 이런 유형의 문제에 대한 대부분의 설명은'D'에서 더 이상 무시하지 않으므로 호출하는 메소드를 정확히 알고 있습니다. –
언어가 객체의 런타임 유형을 기반으로 메서드를 호출하는 방식으로 동작했기 때문에 D 유형의 객체에서 B.foo() 또는 C.foo()를 호출할지 여부가 모호했습니다. . 이 방법으로 처리 되든 설명하는 방식이든 다이아몬드와 삼각형에 공통적 인 것처럼 보입니다. – allstar
이름 조회는 대부분의 언어에서 컴파일 타임에 발생합니다. 두 번째 예제에서, 런타임에, 당신은 "B.foo"또는 더 파생 된 클래스에서'B.foo'의 재정의를 찾을 것입니다. " 당신은 "foo"라고 불리는 메소드를 찾지 않을 것입니다. –