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

Tablica obiektów

Object Storage Arubacloud
0 głosów
406 wizyt
pytanie zadane 23 maja 2020 w C i C++ przez Programmingc100 Bywalec (2,620 p.)

Witam wszystkich, mam pytanie odnośnie zapisu kodu w C ++, poniżej mam kod w którym tworzę tablicę wskaźników na obiekty a jeśli chciałbym utworzyć tablicę obiektów? Takie coś? 

Zwierze *tablica = new Zwierze[3];

 

#include <iostream>
#include <cstdlib>

using namespace std;

class Zwierze {
public:
    virtual void  daj_glos() {
       //
    }
};

class  Kot : public Zwierze {
public:
    void daj_glos() {
       cout<<"Miau "
    }
};

class Pies : public Zwierze {
public:
    void daj_glos() {
       cout<<"Woof "
    }
};

class Krowa : public Zwierze{
public:
    void daj_glos() {
        cout << "Muuuu";
    }
};

int main()
{
    Zwierze **tablica = new Zwierze*[3];

    tablica[0] = new Kot();
    tablica[1] = new Pies();
    tablica[2] = new Krowa();

    for (int i = 0; i<3; i++) {
        tablica[i]->daj_glos();
    }

    system("pause");
    return 0;
}

 

1
komentarz 23 maja 2020 przez DragonCoder Nałogowiec (36,500 p.)
Ale tworzysz dynamiczna tablice 2D, a chcesz uzyc 1D.  Wiec jaki to ma sens? Po zs tym alokujesz pamiec przez wskaznik, ale jej nie zwalniasz. Po to masz vector w jezyku cpp i polecam sie z nim zapoznac

4 odpowiedzi

+2 głosów
odpowiedź 25 maja 2020 przez profesorek96 Szeryf (91,420 p.)
wybrane 13 lipca 2020 przez Programmingc100
 
Najlepsza

Tworząc tablice dynamicznie 1 wymiarową potrzebujesz wskaźnika o danym typie. Za pomocą operatora new alokujesz pamięć. Operator new zwraca adres pierwszego komórki pamięci. Typ wskaźnika określa o ile bajtów należy przeskoczyć by obejmować kolejną komórę pamięci.

Np.

int *tab=new int[3];

Powyższy zapis tworzy tablice dwu wymiarową. Jeśli chcieli byśmy stworzyć tablicę wskaźników. Tablica ta przechowuje nie wartości a adresy. Wtedy należy użyć konstrukcji wskaźnik na wskaźnik. Tablice wskaźników są często używane, jeśli chcieli byśmy stworzyć tablice dwu wymiarową dynamiczną.

//tworzenie tablicy 2d 3x3
int **tab=new int*[3];//tworzymy tablicę wskaźników
for(int i=0;i<3;i++)
{
    tab[i]=new int[3];//do każdego z wskaźników alokujemy pamięć
}

Oczywiście w przypadku tablicy jednowymiarowej wystarczy użyć funkcji delete [] by zwolnić pamięć. W przypadku tablicy 2d wykonali byśmy to w ten sposób.

for(int i=0;i<3;i++)
{
    delete [] tab[i];//zwalniamy pamięć na jaką wskazuje każdy z wskaźników
}
//teraz usuwamy właściwą tablice wskaźników
delete [] tab;

Jeśli chodzi o twój program to mamy do czynienia z zjawiskiem zwanym polimorfizmem. Polimorfizm dynamiczny może tylko i wyłącznie zachodzić wtedy kiedy używamy wskaźników. Na logikę Zwierzę to nie Kot ale Zwierze należy do tej samej rodziny co Kot. Dlatego tutaj należy używać wskaźników. Twój kod powinien wyglądać tak, zapominasz o zwalnianiu pamięci.

#include <iostream>
#include <cstdlib>
 
using namespace std;
 
class Zwierze {
public:
    virtual void  daj_glos() {
       //
    }
};
 
class  Kot : public Zwierze {
public:
    void daj_glos() {
       cout<<"Miau ";
    }
};
 
class Pies : public Zwierze {
public:
    void daj_glos() {
       cout<<"Woof ";
    }
};
 
class Krowa : public Zwierze{
public:
    void daj_glos() {
        cout << "Muuuu";
    }
};
 
int main()
{
    Zwierze **tablica = new Zwierze*[3];
 
    tablica[0] = new Kot();
    tablica[1] = new Pies();
    tablica[2] = new Krowa();
 
    for (int i = 0; i<3; i++) {
        tablica[i]->daj_glos();
    }
    
    //sprzatamy
    for(int i=0;i<3;i++)
    {
    	delete[] tablica[i];
    }
    delete []tablica;
 
    //system("pause");
    return 0;
}

Polimorfizm może istnieć dzięki relacji zwanej dziedziczeniem. To samo co wyżej możesz zrobić z wykorzystaniem kontenerów vector.

#include <iostream>
#include <cstdlib>
#include <vector>
using namespace std;
 
class Zwierze {
public:
    virtual void  daj_glos() {
       //
    }
};
 
class  Kot : public Zwierze {
public:
    void daj_glos() {
       cout<<"Miau ";
    }
};
 
class Pies : public Zwierze {
public:
    void daj_glos() {
       cout<<"Woof ";
    }
};
 
class Krowa : public Zwierze{
public:
    void daj_glos() {
        cout << "Muuuu";
    }
};
 
int main()
{
	vector<Zwierze *> tablica;
	tablica.push_back(new Kot());
	tablica.push_back(new Pies());
	tablica.push_back(new Krowa());
    
    for(int i=0;i<tablica.size();i++)
    {
    	tablica[i]->daj_glos();
    }
    
    return 0;
}

 

+2 głosów
odpowiedź 23 maja 2020 przez j23 Mędrzec (194,920 p.)

Takie coś? 

Takie coś jest OK, jeśli chcesz mieć tablicę obiektów klasy Zwierze. Ta tablica nie ma zastosowania w kodzie, który podałeś. Polimorfizm opiera się na wskaźniku/referencji. Innej opcji nie ma.

+1 głos
odpowiedź 23 maja 2020 przez mokrowski Mędrzec (155,460 p.)

Prawie dobrze. Tylko w kodzie który podałeś, są wycieki pamięci i trochę niezręczności:

#include <iostream>
#include <cstdlib>

using namespace std;

class Zwierze {
public:
    virtual void  daj_glos() const = 0;
    virtual ~Zwierze() {}
};

class  Kot : public Zwierze {
public:
    void daj_glos() const override {
       cout << "Miau ";
    }
};

class Pies : public Zwierze {
public:
    void daj_glos() const override {
       cout << "Woof ";
    }
};

class Krowa : public Zwierze{
public:
    void daj_glos() const override {
        cout << "Muuuu";
    }
};

int main()
{
    Zwierze **tablica = new Zwierze*[3];

    tablica[0] = new Kot();
    tablica[1] = new Pies();
    tablica[2] = new Krowa();

    for (int i = 0; i < 3; ++i) {
        tablica[i]->daj_glos();
    }

    for (int i = 0; i < 3; ++i) {
        delete tablica[i];
    }
    delete [] tablica;

    system("pause");
    return 0;
}

 

2
komentarz 23 maja 2020 przez tkz Nałogowiec (42,000 p.)
IMO tutaj chyba nie ma to aż tak dużego znaczenia, bo i tak program kończy się na wypisaniu, a zwolnieniem pamięci zajmie się system.
1
komentarz 23 maja 2020 przez mokrowski Mędrzec (155,460 p.)
Jak najbardziej w takich przypadkach także należy zwolnić zasoby.
1
komentarz 23 maja 2020 przez tkz Nałogowiec (42,000 p.)
Dlaczego? Nie mówię, że dbanie o pomięć jest zbędne, ale dlaczego akurat tutaj należy ją zwolnić?
2
komentarz 23 maja 2020 przez mokrowski Mędrzec (155,460 p.)
W całej inżynierii oprogramowania, jest zasada by pozostawić stan systemu/modułu/biblioteki/aplikacji taki jak przed wykonaniem operacji. Szczególnie zasada ta kłania się w przypadku testów lub uruchomienia w różnych środowiskach (wirtualne, kontenery, testy itp). Jeśli tego nie robisz, to popełniasz błąd w sztuce. Np. czy wiesz (bo ja nie jestem pewien), jak zadziała taka aplikacja w systemie GNU/Linux z uclibc na platformie na której nie ma zarządzania pamięcią (tak, i na takiej można uruchomić takiego "dziwnego GNU/Linux")? Albo czy działanie programu zaliczy sprawdzarka która weryfikuje zużyte zasoby lub stan po wykonaniu?

Zasada skauta (zostawiam stan jaki zastałem lub ... "lepszy"), to jedna z podstawowych filozofii dobrze wykonanej pracy :-)
1
komentarz 23 maja 2020 przez tkz Nałogowiec (42,000 p.)
Holistycznie na to patrząc masz rację. Skupiłem się na tworze Microsoftu.
0 głosów
odpowiedź 24 maja 2020 przez Programmingc100 Bywalec (2,620 p.)

Czyli nie można napisać tablicy obiektów  z różnych klas nie używając do tego wskaźników? Co najwyżej w ten sposób:

Zwierze tablica[3] = {Kot(), Pies(), Krowa()};

for (int i = 0; i < 3; i++) 
cout << "Głos:" << tablica[i].daj_glos() << endl;

Ale wtedy nie otrzymam nic, bo tylko to co jest w metodzie wirtualnej.

1
komentarz 24 maja 2020 przez tkz Nałogowiec (42,000 p.)
To się nawet nie skompiluje.
1
komentarz 24 maja 2020 przez j23 Mędrzec (194,920 p.)

@Programmingc100,

Co najwyżej w ten sposób:

Ale to cały czas jest tablica obiektów klasy Zwierze i daj_glos będzie w wersji zaimplementowanej w tej klasie.

 

PS. dyskusje prowadzimy w komentarzach.

Podobne pytania

0 głosów
1 odpowiedź 175 wizyt
pytanie zadane 5 kwietnia 2021 w C i C++ przez Paweł Środek Nowicjusz (200 p.)
0 głosów
1 odpowiedź 360 wizyt
pytanie zadane 7 maja 2020 w C i C++ przez Programmingc100 Bywalec (2,620 p.)
0 głosów
1 odpowiedź 625 wizyt

92,555 zapytań

141,403 odpowiedzi

319,557 komentarzy

61,940 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!

...