• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed Dziedzieczenie wirtualne, dzielenie podobiektu.

Object Storage Arubacloud
+1 głos
183 wizyt
pytanie zadane 17 września 2018 w C i C++ przez Jakub 0 Pasjonat (23,120 p.)
zamknięte 5 października 2018 przez Jakub 0

Witam, wiem że dzięki dziedziczeniu wirtualnemu możemy zastosować dziedziczenie wielokrotne z klas związanych ze sobą w takowy sposób:

jak B1 i B2.

Mój przykładowy kod:

#include <iostream>

///----------------------------------------------------------------------------

class Base {

private:
    int a;

protected:
    virtual void get(std::istream& is){
        is >> a;
    }

   virtual void data(std::ostream& os) const {
        os << a;
    }

public:
    Base(int v1) : a(v1) {}
    virtual void show(std::ostream& os) const = 0;
    virtual void read(std::istream& is) = 0;

    virtual ~Base() {}
};

///-------------------------------------------------------------------------------------


class DerivativeA : virtual public Base {
private:
    int b1;

protected:
    virtual void get(std::istream& is){
        is >> b1;
    }

    virtual void data(std::ostream& os) const {
        os << b1;
    }

public:
    DerivativeA(int v1, int v2) : Base(v1), b1(v2) {}

    virtual void show(std::ostream& os) const {
        Base::data(os);
        os<<std::endl;
        data(os);
    }

    virtual void read(std::istream& is) {
        Base::get(is);
        get(is);
    }
};

///-------------------------------------------------------------------------------------

class DerivativeB : virtual public Base {
private:
    int b2;

protected:
    virtual void get(std::istream& is){
        is >> b2;
    }

    virtual void data(std::ostream& os) const {
        os << b2;
    }

public:
    DerivativeB(int v1, int v2) : Base(v1), b2(v2) {}

    virtual void show(std::ostream& os) const {
        Base::data(os);
        os<<std::endl;
        data(os);
    }

    virtual void read(std::istream& is) {
        Base::get(is);
        get(is);
    }
};

///-----------------------------------------------------------------------------------

class Derivative : public DerivativeA, public DerivativeB {

private:
    int c;

protected:
    virtual void get(std::istream& is){
        is >> c;
    }

    virtual void data(std::ostream& os) const {
        os << c;
    }

public:
    Derivative(int v1, int v2_A, int v2_B, int v3) :
         Base(v1), DerivativeA(v1,v2_A),
         DerivativeB(v1,v2_B), c(v3)
      {}

    virtual void show(std::ostream& os) const {
        Base::data(os);
        os<<std::endl;
        DerivativeA::data(os);
        os<<std::endl;
        DerivativeB::data(os);
        os<<std::endl;
        data(os);
    }

    virtual void read(std::istream& is) {
        Base::get(is);
        DerivativeA::get(is);
        DerivativeB::get(is);
        get(is);
    }
};

///-------------------------------------------------------------------------------------

int main(){

    DerivativeA da(12,1);
    da.show(std::cout);
    std::cout<<std::endl;
    DerivativeB db(13,2);
    db.show(std::cout);
    std::cout<<std::endl;
    da.show(std::cout);
    std::cout<<std::endl;

    Derivative d(1,2,3,4);
    d.show(std::cout);
    std::cout<<std::endl;
}

Z tego co się orientuję to dziedziczenie wirtualne z klasy Base sprawia że obiekty klas DerivativeA i DerivativeB dzielą ze sobą wspólny podobiekt klasy Bazowej. To też sprawia że klasa dziedzicząca wielokrotnie: Derivative, nie odziedziczy nadmiaru ( tutaj dwóch ) egzemplarzy ( obiektów ) klasy Base. To też wymusza na nas zastosowania odpowiednich zmian w konstruktorze klasy Derivative:

Derivative(int v1, int v2_A, int v2_B, int v3) :
         Base(v1), DerivativeA(v1,v2_A),
         DerivativeB(v1,v2_B), c(v3)
      {}

Jednak jest tu rzecz której nie rozumiem, ten fragment:

DerivativeA da(12,1);
da.show(std::cout);

DerivativeB db(13,2);
db.show(std::cout);

da.show(std::cout);

skoro obiekty da i db zawierają w sobie wspólny podobiekt klasy Base to dlaczego w chwili inicjalizacji:

DerivativeB db(13,2);

dane obiektu da ( należące do wspólnego obiektu obu klas ) nie zostaną utracone? Przecież powędrowała tam wartość 13, a nadal wypisuje się 12.

Możliwe też że je to dziedziczenie wirtualne źle rozumiem ( na pewno skoro zadałem to pytanie ;) ) Skłaniam się do wniosku że efekty zastosowania tego dziedziczenia są widoczne jedynie w chwili zastosowania dziedziczenia wirtualnego. Bo gdyby to było tak za każdym razem to nie miało by to ani sensu, ani logiki...

Czy dobrze to sobie wytłumaczyłem?

Z góry dziękuję za pomoc :)

komentarz zamknięcia: temat wyczerpany
komentarz 19 września 2018 przez draghan VIP (106,230 p.)
Jeśli Criss pomógł Ci w zrozumieniu swoją odpowiedzią, daj najkę. ;)

1 odpowiedź

0 głosów
odpowiedź 17 września 2018 przez criss Mędrzec (172,590 p.)
wybrane 5 października 2018 przez Jakub 0
 
Najlepsza

Jakoś strasznie dziwnie myślisz. 

wiem że dzięki dziedziczeniu wirtualnemu możemy zastosować dziedziczenie wielokrotne z klas związanych ze sobą w takowy sposób:

W ramach jednego obiektu. Jeśli masz klase A, oraz klasy B1 oraz B2 dziedziczące z A, oraz klase C dziedziczącą z obu B1 i B2, to "diamond problem" pojawia się na poziomie klasy C. Zaprezentowany przez ciebie kod (ten z obiektami `da` i `db`) w ogóle nie ma tego problemu. `da` jest obiektem typu DerivativeA i ma swój podobiekt Base, a `db` jest typu DeriavtiveB i ma swój podobiekt Base. To nie jest tak, że wszystkie instancje klas dziedziczących z Base mają wspólny podobiekt w sensie obszaru pamięci. `da` jest niezależnym obiektem oraz `db` jest niezależnym obiektem i oba zawierają osobną instancje Base.

komentarz 17 września 2018 przez Jakub 0 Pasjonat (23,120 p.)
Czyli rozumiem że obiekty klas (np. B1, B2) dzielą ze sobą wspólny podobiekt klasy bazowej tylko w przypadku dziedizczenia z nich jeszcze jednej klasy?
komentarz 17 września 2018 przez criss Mędrzec (172,590 p.)
No słuchaj, jeśli masz taką hierarchie: A->B->C (B dziedziczy z A, C dziedziczy B), to C zawiera B oraz A. W przypadku przedstawionym przez ciebie na początku dziedziczenie wirtualne zapewnia, że jeśli C dziedziczy z B1 oraz B2, to nie będzie zawierać dwóch instancji obiektu A, tylko jedną.

Nie wiem czy rozumiesz, bo twoje pytania są strasznie dziwne i wydaje mi się, że zupełnie nie rozróżniasz obiektu i klasy.
komentarz 17 września 2018 przez Jakub 0 Pasjonat (23,120 p.)
edycja 17 września 2018 przez Jakub 0

Nie wiem czy rozumiesz, bo twoje pytania są strasznie dziwne i wydaje mi się, że zupełnie nie rozróżniasz obiektu i klasy.

Jak najbardziej rozróżniam obiekt od klasy ( klasa to opis typu a obiekt to konkretny egzemplarz klasy - stworzony z tego opisu ). Tylko możliwe że kilka razy przez mój błąd użyłem tu zamiennych słów bo ogólnie temat mi się skomplikował. 

W przypadku przedstawionym przez ciebie na początku dziedziczenie wirtualne zapewnia, że jeśli C dziedziczy z B1 oraz B2, to nie będzie zawierać dwóch instancji obiektu A, tylko jedną.

Czyli  w takim razie chyba dobrze tu stwierdziłem:

Czyli rozumiem że obiekty klas (np. B1, B2) dzielą ze sobą wspólny podobiekt klasy bazowej tylko w przypadku dziedziczenia z nich jeszcze jednej klasy?

Może trochę źle tu dobrałem słownictwo... miałem po prostu na myśli że dziedziczenie wirtualne jest przeznaczone dla takich sytuacji. Czyli kiedy utworzymy obiekt klasy C to dzięki dziedziczeniu wirtualnemu jej klas bazowych, B1 i B2  z klasy A, obiekt kasy C będzie zawierać tylko jeden obiekt klasy A. ( czyli obiekty klas bazowych B1 i B2  będą dzielić w sobie jeden podobiekt klasy A ).

Co ja tu źle piszę?

 

 

To nie jest tak, że wszystkie instancje klas dziedziczących z Base mają wspólny podobiekt w sensie obszaru pamięci. `da` jest niezależnym obiektem oraz `db` jest niezależnym obiektem i oba zawierają osobną instancje Base.

To zdanie przeczytałem drugi raz i temat raczej zrozumiałem. Ciekawy jestem tylko co złego jest w mojej powyższej interpretacji.

* Dziękuję za pomoc i cierpliwość, czasami coś łatwo załapuje a czasami jest tragedia, jak widzisz... :/

Podobne pytania

0 głosów
1 odpowiedź 259 wizyt
pytanie zadane 29 maja 2018 w C i C++ przez Jakub 0 Pasjonat (23,120 p.)
0 głosów
1 odpowiedź 550 wizyt
pytanie zadane 10 listopada 2017 w C i C++ przez Poczatkujacy Nowicjusz (150 p.)
+1 głos
1 odpowiedź 287 wizyt

92,576 zapytań

141,426 odpowiedzi

319,650 komentarzy

61,961 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...