2014-05-10 7 views
13

는 클래스 D 가정 및 E와 F는 모두 기본 클래스 B에서 상속, 그 클래스 C는 D와 E다이아몬드 상속

에서 상속

매수를 클래스 B의이 클래스 C에 표시 (I)?

(ii) 어떻게 가상 상속을 사용하면이 시나리오가 바뀔까요? 귀하의 답변을 설명하십시오.

(iii) 많은 경우 C++에서 다중 상속이 사용될 수있는 상황에서 Java가 다중 상속을 피할 수 있습니까?

여기 현재 제 아이디어 중 일부는 있지만, C++ 전문가는 아닙니다.

(i) C가 B의 하위 클래스 인 D와 E를 상속하는 경우 D와 E는 기술적으로 수퍼 클래스 사본입니까? 그렇다면 C가 D와 E에서 상속하면 C에 B가 2 개 있다는 것을 의미합니다.

(ii) 가상을 사용하는 것은 Java에서 Abstract를 사용하는 것과 다소 비슷합니다. 이제는 인스턴스화가 필요한 수준까지 계단식으로 배치되므로 C에 B가 여러 개 없을 것입니다. 나는 내 설명에 단어를 쓰는 방법을 모르지만 B에 print()라는 함수가 있고 "나는 B"이고 C는이 함수를 덮어 쓰고 "나는 C"라고 쓰여 있다고 말합니다. 가상 (virtual)을 사용하지 않고 C에서 print()를 호출하면 "i am B"가 인쇄되고 가상을 사용하면 "i am C"가 인쇄됩니다.

(iii) 제 아이디어는 자바가 다중 상속의 사용을 피하기 위해 인터페이스를 사용할 수 있다는 것입니다. 여러 인터페이스를 구현할 수 있지만 하나의 클래스 만 확장 할 수 있습니다. 여기에 추가 할 항목이 무엇인지 확실하지 않으므로 입력이나 관련 리소스가 도움이됩니다.

+2

+1 "나는 도움이 필요하지만 내가 시도한 것을 털어 놓는다."라는 질문의 훌륭한 예입니다. 질문 – yizzlez

+1

'(ii)'에 대한 짧은 대답은 B 복사본이 하나 밖에 없다는 것입니다. 더 – yizzlez

+2

+1, 이것은 또한 당신을 도울지도 모른다 : http://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem –

답변

3

(i) 및 (iii)이 옳다. 어쨌든 내 경험상 C++에서 대부분의 시간은 다중 상속을 사용했을 때 기본이 인터페이스 (C++에서 키워드를 지원하지 않지만 어쨌든 실행할 수있는 개념) 때문이었습니다.

(ii)의 첫 번째 문장은 맞지만 두 번째 문장은 가상 함수와 완전히 다른 가상 상속에 대한 이야기입니다. 가상 상속은 B의 복사본이 하나 뿐이며 DE은 모두 기본 복사본과 동일한 복사본을 가지고 있음을 의미합니다. 함수 측면에서는 차이점이 없지만 차이점은 멤버 변수 (및 기본 클래스)는 B입니다.

B의 멤버 변수 foo을 출력하는 함수가있는 경우; (ⅱ)의 경우이 함수는 항상 하나의 foo 만 있기 때문에 항상 동일한 값을 인쇄하지만, (i) D 기본 클래스의 해당 함수를 호출하면 E 기본 클래스에서 호출 할 때 다른 값이 인쇄 될 수 있습니다.

용어 "다이아몬드 상속은"좋은 기억을 돕는 역할 :

+0

감사합니다. Matt. 나는이 과정을 더 자세히 살펴볼 것입니다. 코스 재료가 제대로 전달되지 못했기 때문에 여기에 깊이 들어가 있습니다. –

1

당신은 추론 작업을 필요로하지만 대부분, 정답에 도착했습니다 것 같다 두 단어로 모든 것을 감싼다. 여기서 중요한 문제는 "동일한 기본 클래스를 두 번 상속받는 경우 C 인스턴스의 메모리를 레이아웃하는 방법"에 대한 질문입니다.

i) C 유형의 객체에 대한 메모리 레이아웃에 기본 클래스 B 사본이 2 개 있습니다.제공된 예제는 "다이아몬드 상속"의 경우입니다. 왜냐하면 종속성/상속 트리를 그릴 때 본질적으로 다이아몬드를 그리기 때문입니다. 다이아몬드 상속의 "문제"는 본질적으로 객체를 메모리에 두는 방법을 묻는 것입니다. C++은 데이터 멤버를 복제하는 빠른 방법과 느린 방법 인 "가상 상속"의 두 가지 접근 방식을 사용했습니다. 비 가상 접근법을 사용하는 이유는 데이터 멤버가없는 클래스 (Java의 인터페이스)를 상속하는 경우 존재하지 않기 때문에 "데이터 멤버 복제"에 문제가 없다는 것입니다 하단의 내 노트 참조). 계획 상 하나의 상속 만 사용하려는 경우 비 가상 상속을 사용하는 것이 좋습니다.

ii) virtual class C이있는 경우 컴파일러에서 영웅 행위를 수행하여 모든/모든 기본 클래스의 복사본이 하나만 있는지 확인하려는 C++ 언어를 말합니다. 파생 된 클래스의 메모리 레이아웃. 나는 또한 이것이 약간의 성능에 영향을 미친다고 생각한다. 이제 'C'인스턴스의 'B'멤버를 사용하면 항상 메모리의 같은 위치를 참조합니다. 가상 상속은 함수이 가상인지 여부에 영향을주지 않습니다.

별도 : 이것은 추상적 인 클래스의 개념과 완전히 관련이 없습니다. C++에서 추상 클래스를 만들려면 void foo() = 0;에서와 같이 메서드 선언 = 0을 설정합니다. (소멸자를 포함하여) 모든 메소드에 대해 그렇게하면 클래스 전체를 추상화하는 데 충분합니다.

iii) Java outright는 금지합니다. Java에는 단일 상속과 인터페이스 수를 구현하는 기능이 있습니다. 인터페이스는 "is-a"관계와 가상 함수를 갖는 기능을 제공하지만 인터페이스는 데이터 멤버를 추가 할 수 없으므로 데이터 레이아웃과 다이아몬드 상속으로 C++가 갖는 문제를 암시 적으로 피합니다. 데이터 멤버의 위치를 ​​어떻게 해결할 지에 대한 혼란.

중요한 확장 기능은 "동일한 인터페이스를 두 번 구현"하는 경우 가상 함수 호출 디스패치가 전혀 영향을받지 않는다는 것을 인식하는 것입니다. 그 이유는 가상 테이블에 여러 복사본이 있더라도이 메서드는 항상 동일한 작업을 수행하기 때문입니다. 그것은 당신의 클래스의 데이터에만 작용하고, 그 자체는 명확성을 필요로하는 데이터를 포함하지 않습니다.