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

question-closed C++, dziedziczenie. Problem związany ze wskaźnikiem klasy bazowej na klasę pochodną.

Aruba Cloud VPS - 50% taniej przez 3 miesiące!
0 głosów
837 wizyt
pytanie zadane 1 czerwca 2018 w C i C++ przez Jakub 0 Pasjonat (23,120 p.)
zamknięte 1 czerwca 2018 przez Jakub 0

Witam, myślałem że tym razem obejdzie się bez większych problemów ale C++ znowu stawia mi figle których ja nie potrafię zrozumieć ;( Mam taki banalny przykład dziedziczenia:

class A {
	int a;
public:
	A(int v) : a(v) {}

	int& returna() {
		return a;
	}
};

class B : public A {
	int b;
public:
	B(int v1, int v2) : A(v1), b(v2) {}

	int& returnb() {
		return b;
	}
};

I takie dynamiczne przydzielenie:

A* aaa = new B(1,2);

Odwołanie się:

aaa->returna();

Jest poprawne, ale:

aaa->returnb();

Powoduje błąd kompilacji że klasa 'A' nie posiada takiej metody. Ale zaraz, przecież wskaźnik klasy 'A' wskazuje na dynamicznie przydzielony obiekt pamięci klasy 'B'.

B bbb(2, 2);
A* aaa = &bbb;
aaa->returna();
aaa->returnb(); //to też powoduje błąd 

Czy naprawdę nie da się odwołać do składowej klasy pochodnej za pomocą wskaźnika lub referencji typu klasy bazowej? Jeśli tak, a problem nie wynika z mojego niedopatrzenia to mega słabo :/ ( dziedziczenie traci trochę sensu w moich oczach )

* wiem oczywiście o metodach wirtualnych, ale to tylko inna postać metody o takiej samej nazwie w klasie pochodnej.

komentarz zamknięcia: już znam wytłumaczenie

1 odpowiedź

0 głosów
odpowiedź 1 czerwca 2018 przez criss Mędrzec (172,590 p.)
wybrane 1 czerwca 2018 przez Jakub 0
 
Najlepsza
Wszystko jest ok - tak ma być. Dziedziczenie działa w strone od bazowej do pochodnej (jak nazwa wskazuje :D) tzn B dziedziczy elementy A, nie odwrotnie.
komentarz 1 czerwca 2018 przez Jakub 0 Pasjonat (23,120 p.)

To niezbyt fajnie bo widziałem zastosowanie dla czegoś takiego... Ale C++ zmienić nie potrafię ( i tak ma za dużo możliwości jak na moją głowę i to trzeba cenić laugh ). Mam tylko jedno dodatkowe pytanie dotyczące destruktorów wirtualnych:

A* aaa = new B(1,2);
delete aaa; // zwolnienie pamięci 

Skoro dla obiektu klasy 'B' wykona się destruktor tylko klasy 'A' ( bo nie jest on wirtualny i ma jedną postać - postać dla typu referencji lub wskaźnika ). To obiekt nie zostanie zwolniony w całości? Tzn. czy zwolniony zostanie tylko pod obiekt odziedziczony z klasy 'A'?

komentarz 1 czerwca 2018 przez criss Mędrzec (172,590 p.)

Tak, dokładnie, dlatego najlepiej zawsze tworzyć wirtualny destruktor jeśli dana klasa ma być bazową.

komentarz 1 czerwca 2018 przez Jakub 0 Pasjonat (23,120 p.)
Dziękuje, to wszystko
1
komentarz 1 czerwca 2018 przez criss Mędrzec (172,590 p.)
Ah chwileczka, chyba nie do końca dobrze zrozumiałem Twoje pytanie. Obiekt zostanie zwolniony cały (tzn. pamięć w której "mieszkał", tak mi się wydaje przynajmniej.. nie widze powodu dla którego miałoby tak nie być bo to ten sam blok pamięci, ale nie jestem 100% pewien), ale nie zostanie uruchomiony destruktor B. Więc jeśli w destruktorze B dzieje się coś ważnego (zamykanie pliku, zwalnianie innej pamięci...), to to się nie stanie dopóki destruktor A nie będzie virtual lub wskaźnik `aaa` nie będzie typu B*.
komentarz 2 czerwca 2018 przez Jakub 0 Pasjonat (23,120 p.)

W mojej książce ( C++, Szkoła Programowania ) :

 

Pisze tu oczywiście o przypadku jeżeli w klasie pochodnej obsługujemy pamięć dynamiczną. Jednak jest tu wzmianka że wywołanie delete ( bez destruktora wirtualnego ) zwolni z pamięci składowe klasy bazowej, "ale już nie pamięci zajmowanej przez nowe składowe tak klasy ( pochodnej )". Pisze tu ogólne składowe a nie tylko o pamięci na którą wskazuje wskaźnik char*. Tak jak by część zawartości klasy pochodnej tkwiła potem w pamięci. No chyba że nie przeczytałem tego ze zrozumieniem :/

komentarz 2 czerwca 2018 przez monika90 Pasjonat (22,940 p.)
Bez znajomości szczegółów konkretnej implementacji C++ nie wiadomo co się stanie, bo zachowanie jest niezdefiniowane.

Podobne pytania

0 głosów
2 odpowiedzi 1,040 wizyt
0 głosów
1 odpowiedź 1,375 wizyt

93,164 zapytań

142,176 odpowiedzi

321,933 komentarzy

62,491 pasjonatów

Advent of Code 2024

Top 15 użytkowników

  1. 688p. - dia-Chann
  2. 676p. - CC PL
  3. 675p. - Łukasz Piwowar
  4. 662p. - Łukasz Eckert
  5. 649p. - Michal Drewniak
  6. 641p. - rucin93
  7. 621p. - Dawid128
  8. 572p. - ssynowiec
  9. 457p. - Marcin Putra
  10. 432p. - rafalszastok
  11. 427p. - Adrian Wieprzkowicz
  12. 425p. - zmmz89
  13. 417p. - Mikbac
  14. 414p. - Piotr Aleksandrowicz
  15. 412p. - ksalekk
Szczegóły i pełne wyniki

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

Wprowadzenie do ITsec, tom 1 Wprowadzenie do ITsec, tom 2

Można już zamawiać dwa tomy książek o ITsec pt. "Wprowadzenie do bezpieczeństwa IT" - mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy aż 15% zniżki! Dziękujemy ekipie Sekuraka za fajny rabat dla naszej Społeczności!

...