2016-10-09 30 views
5

Mam klasę podstawową o nazwie zwierzę, oraz psa i kota, który dziedziczy po Zwierzęciu. I klasa wielorakościowa o nazwie dogcat, która dziedziczy od psa i kota, w grze Animal i mam metodę zwaną snem. Kiedy chcę użyć tej metody z dogcat, pojawia się błąd "DogCat :: sleep" jest niejednoznaczny, rozumiem problem, ale czytam w książce, że powinno być możliwe, kiedy deklarujesz sen jako wirtualny - ale to nie działa.Niejednoznaczne obejście dla wielowątkowości?

Czy to nie jest możliwe, czy książka jest błędna, czy istnieje jakieś obejście tego problemu?

class Animal 
{ 
public: 
    Animal(){} 

    virtual void sleep() 
    { 
     cout << "zzzzzzzzz" << endl; 
    } 
    virtual void eat() = 0; 

}; 

class Dog: public Animal 
{ 
protected: 
    Dog(){} 

    virtual void eat() override 
    { 
     cout << "eats dogfood" << endl; 
    } 
}; 

class Cat :public Animal 
{ 
public: 
    Cat(){} 
    virtual void eat() override 
    { 
     cout << "eats catfood" << endl; 
    } 
}; 

class DogCat : public Dog, public Cat 
{ 
public: 
    DogCat(){} 
    using Dog::eat; 

}; 

int main(int argc, char** argv) { 
    DogCat *DC = new DogCat(); 
    DC->sleep();//Error 
} 
+0

Ile zwierząt znasz, to zarówno kot jak i pies? – Peter

+0

imho większość przypadków problemu z diamentem wskazuje na słabą klasę. A twoja sprawa zdecydowanie mieści się w tej kategorii. – user463035818

Odpowiedz

6

Masz diamond problem

enter image description here

"problem diament" (czasem określane jako „śmiertelną diamentu śmierci "[4]) jest niejednoznacznością, która pojawia się, gdy dwie klasy B i C dziedziczą z A, a dziedziczenie klasy D s zarówno z B, jak i C. Jeśli istnieje metoda w A, którą B i C zastąpiły, a D jej nie zastępuje, to która z wersji metody dziedziczy: D B lub C?

Tak. Teraz masz dwa wystąpienia A. Jakie jest rozwiązanie? Masz dwa:

  1. Zdefiniuj wyłącznik czasowy w jednym z subclases i nazywają go:
class Cat :public Animal 
{ 
    public: 
     Cat(){} 
     virtual void eat() override 
     { 
      cout << "eats catfood" << endl; 
     } 

     void sleep() 
     { 
      Animal::sleep(); 
     } 
}; 

int main(int argc, char** argv) { 
    DogCat *DC = new DogCat(); 
    DC->Cat::sleep(); 
} 
  1. Używaj wirtualnego dziedziczenie jak mówi @Asesh odpowiedź. Problemem jest powszechna metoda eat(). Musisz to zmienić.
+2

możesz usunąć' Cat :: sleep', ale zaimplementuj 'DogCat :: sleep', nazywając' Cat :: sleep', który naturalnie nazwie 'Animal :: sleep' przez' Cat 'ścieżka. – Franck

3

Należy użyć wirtualnego dziedziczenie

class Animal 
{ 
public: 
    Animal(){} 

    virtual void sleep() 
    { 
     cout << "zzzzzzzzz" << endl; 
    } 
    virtual void eat() = 0; 

}; 

class Dog: virtual public Animal 
{ 
protected: 
    Dog(){} 

    virtual void eat() override 
    { 
     cout << "eats dogfood" << endl; 
    } 
}; 

class Cat : virtual public Animal 
{ 
public: 
    Cat(){} 
    virtual void eat() override 
    { 
     cout << "eats catfood" << endl; 
    } 
}; 

class DogCat : public Dog, public Cat 
{ 
public: 
    DogCat(){} 
    using Dog::eat; 

}; 

int main(int argc, char** argv) { 
    DogCat *DC = new DogCat(); 
    DC->sleep();//Error 
} 
+2

To jest właściwa odpowiedź. Jednak byłoby miło rozwinąć nieco dalej, aby OP zrozumiał problem z diamentem i dlaczego ma on niejednoznaczność (tj. Wiele przykładów zwierząt) i jak rozwiązuje to twoje wirtualne rozwiązanie dziedziczenia. – Christophe

+0

@Christophe To nadal się nie kompiluje: http://coliru.stacked-crooked.com/a/07dafb58241bc191 – xinaiz

+0

To działa na sen, ale musiałem przesłonić jeść w DogCat, aby go do pracy, powiedział, zastąpić wirtualny funkcja "Animal :: eat" jest niejednoznacznym i niejednoznacznym dziedzictwem "void Animal :: eat (void)" – Niklas