2013-05-15 21 views
8

Widziałem wiele przykładów, które ilustrują niebezpieczeństwa wielokrotnego dziedziczenia.Dlaczego diament śmierci, a nie trójkąt śmierci

Przykładem jest jak zwykle klas B i C obejmuje Klasy A, D obejmuje zarówno B i C

B i C, jak zastąpić metodę z A, powiedzmy na przykład, równa();

następnie po wywołaniu D.equals(); nie wiemy, który z jego rodzic powinien być nazywany

pod warunkiem, że jest równy() nie jest uwzględniana w D.

Z tego co widzę, nie jest klasa A w tym przypadku zbędny? Jeśli usuniemy A z tej hierarchii i po prostu spojrzymy na B i C, jeśli oba B i C mają metodę zwaną equals(), to kiedy D rozszerzy B i C, to nadal będzie miał ten sam problem, więc czy tak naprawdę nie jest to trójkąt śmierci?

Nie jestem pewien, czy to, co zakładałem, spowoduje błąd czasu kompilacji w innym języku.

Mam nadzieję, że ktoś może to dla mnie wyjaśnić.

+3

Czy to nie byłoby "V of Death"? – Craig

+0

Myślę, że to pytanie związane z projektem jest lepiej dostosowane do http://programmers.stackexchange.com/. –

+0

Myślę, że "diament" po prostu ilustruje, że zarówno klasa B, jak i C rozszerzają klasę A, nawet jeśli sama A nie powoduje żadnych problemów. – Janman

Odpowiedz

1

Jeśli D extends B and C nie zastępuje metodę equals(), który jest realizowany w części B i C, nie ma wątpliwości - D może wykorzystywać B.equals() lub C.equals().

o strukturze diamentu, z drugiej strony, jeśli D wzywa A.equals() i zarówno bic go zastąpić, nie wiem, która metoda powinna być wywoływana B.equals() lub C.equals().

+1

Mówisz, co mówisz? Co jeśli metody 'równe' w' B' i 'C' są całkowicie różne?Jeśli 'D' może używać' B' _or_ 'C', wydaje mi się, że istnieje niejasność. Który należy wybrać? – paxdiablo

+0

To znaczy, nie ma dwuznaczności z punktu widzenia egzekucji. –

+0

Cóż, teraz mnie zgubiłeś. Jeśli 'B.equals()' zwraca przyzwoitą wartość i 'C.equals()' również zwraca tę wartość, ale po sformatowaniu dysku twardego, co powinien zrobić 'D.equals()'? W każdym razie wydaje się, że jest to dupe, więc prawdopodobnie powinno zostać zamknięte. – paxdiablo

0

Masz rację, nie ma potrzeby, aby w ogóle istniała A, aby pokazać problemy związane z dziedziczeniem wielokrotnym.

następujący kod ("V śmierci", jak Craig wymownie stawia go w komentarzu) wystarczy:

#include <iostream> 

class xyzzy { 
    public: virtual int get (void) { return 7; } 
}; 

class plugh { 
    public: virtual int get (void) { return 42; } 
}; 

class twisty: public xyzzy, public plugh { 
}; 

int main() { 
    twisty passages; 
    std::cout << passages.get() << '\n'; 
    return 0; 
} 

Przy próbie kompilacji tego dostaniesz:

testprog.cpp: In function ‘int main()’: 
testprog.cpp:16:24: error: request for member ‘get’ is ambiguous 
testprog.cpp:8:14: error: candidates are: virtual int plugh::get() 
testprog.cpp:4:14: error:     virtual int xyzzy::get() 

Pamiętaj jednak, że możesz jawnie wybrać, który chcesz, z czymś podobnym:

std::cout << passages.plugh::get() << '\n'; 

Więcej informacji na temat problemu z diamentem: here, w tym dlaczego tak naprawdę jest to inny problem.

+0

To dziwne, że ludzie nazywają to "śmiercią", ponieważ istnieje jawna składnia wywołania 'passages.xyzzy :: get()' i sprawia, że ​​twoje intencje są oczywiste. – nurettin

+0

Myślę, że teraz rozumiem to lepiej, myślę, że to spowoduje błąd kompilacji, gdzie jako przykład diamentu nie spowoduje błędu kompilacji, ale spowoduje to błąd czasu wykonywania? – grumpynerd

Powiązane problemy