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

Dynamiczne dodawanie i usuwanie obiektów klasy abstrakcyjnej

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

Witam. Powiedzmy że mam taką hierarchie klas jak w poprzednim wątku i chcę teraz stworzyć program który może dodawać, usuwać dynamicznie zwierzęta i jeszcze jakieś inne opcje(np zmieniać ich parametry). Myślę, że najlepiej będzie do tego użyć kontenera vector(dodawanie  metodą push_back() a usuwanie metodą erase() ). Tylko mam problem z tym, że powiedzmy użytkownik musi wybrać jakie zwierze chce dodać(Kota,Psa czy Krowe) i jak to rozpoznać, próbowałem w spsób jak poniżej ale nie wypaliło

 

#include <iostream>
#include <cstdlib>
#include <string>
#include <vector>

using namespace std;

class Zwierze
{
public:
    string nazwa;
    string kolor;
    int rozmiar;
    int wiek;
    Zwierze(){}
    Zwierze(string kolor,int rozmiar,int wiek)
    {

        this->kolor = kolor;
        this->rozmiar = rozmiar;
        this->wiek = wiek;
    }
    virtual void  daj_glos()
     {
       //
     }
};
class  Kot : public Zwierze
{
public:
    string nazwa = "Kot";
    string kolor;
    int rozmiar;
    int wiek;
    Kot(){}
    Kot(string kolor,int rozmiar,int wiek)
    {

        this->kolor = kolor;
        this->rozmiar = rozmiar;
        this->wiek = wiek;
    }
    void daj_glos() {
       cout<<"Miau ";
    }
    ~Kot() {}
};
class Pies : public Zwierze
{
public:
     string nazwa = "Pies";
     string kolor;
     int rozmiar;
     int wiek;
     Pies(){}
     Pies(string kolor,int rozmiar,int wiek)
    {

        this->kolor = kolor;
        this->rozmiar = rozmiar;
        this->wiek = wiek;
    }
    void daj_glos()
    {
       cout<<"Woof ";
    }
     ~Pies() {}
};
class Krowa : public Zwierze
{
public:
     string nazwa = "Krowa";
     string kolor;
     int rozmiar;
     int wiek;
     Krowa(){}
    Krowa(string kolor,int rozmiar,int wiek)
    {

        this->kolor = kolor;
        this->rozmiar = rozmiar;
        this->wiek = wiek;
    }
    void daj_glos()
     {
        cout << "Muuuu";
     }
      ~Krowa() {}
};
int main()
{
    int n;

      string name;
      string imie;
      int wiek,rozmiar;

     vector<Zwierze*>tablica;
     cout<<"MENU: 1: Dodaj nowe zwierze: \n 2: Usun zwierze: \n 3: Edytuj zwierze \n 4:  Daj Glos \n 5: Wyjdz \n ";
     cin>>n;
    while(n!=5)
   {

       switch(n)
       {
           case 1:
          {
            cin.ignore();
            cout<<"Pojda nazwe zwierzecia ktore chcesz dodac: "<<endl;
            getline(cin,name);
            cout<<"Pojda imie dla zwierzecia ktore chcesz dodac: "<<endl;
            getline(cin,imie);
            cout<<"Pojda rozmiar zwierzecia ktore chcesz dodac: "<<endl;
            cin>>rozmiar;
            cout<<"Pojda wiek zwierzecia ktore chcesz dodac: "<<endl;
            cin>>wiek;
            Zwierze *zwierze = new Zwierze(imie,rozmiar,wiek);
           if(zwierze->nazwa==name)
            tablica.push_back(zwierze);
             else
                cout<<"Nie ma takiego zwierzecia"<<endl;
            break;
         }
           case 2:
            {
                break;
            }
           case 3:
            {
                break;
            }
           case 4:
            {
                break;
            }
           case 5:
            {
                break;
            }
          cout<<"Wybierz numer lub wyjdz: "<<endl;
    }
  }
 return 0;
}

 

 

1
komentarz 28 maja 2020 przez j23 Mędrzec (194,920 p.)

Owszem, pod warunkiem, że jego destruktor zostanie wywołany.

Prosty przykład:

struct X { 
    ~X() { std::cout << "~X()\n"; } 
};

struct A { 
    virtual ~A() {} // usuń virtual
};

struct B : public A { X x; };


int main()
{
    A *p = new B;
    delete p;
}

 

1
komentarz 28 maja 2020 przez tkz Nałogowiec (42,000 p.)
Dzięki, stało się jaśniejsze. Myślałem, że string mimo wszystko się tym sam zajmie.
1
komentarz 28 maja 2020 przez j23 Mędrzec (194,920 p.)
String zajmie się tylko pamięcią, którą sam przydzielił, ale by to zrobić, musi być wywołany jego destruktor, a ten jest wywoływany w destruktorze klasy, której jest polem. Jeśli destruktor klasy nie jest wywołany, to i string nie jest niszczony, a to oznacza potencjalny  wyciek pamięci. Dlatego uważam, że jak stosujesz dziedziczenie z myślą o polimorfizmie, to warto destruktor robić wirtualnym.
1
komentarz 28 maja 2020 przez DragonCoder Nałogowiec (36,500 p.)
Dodanie jednego virtual przy dekonstruktorze, nawet i 20 w sporym projekcie nie bedzie naduzyciem chyba, a zawsze to potencjalne zabezpieczenie przed wyciekiem. Tak wiec chyba lepiej jest zyc z tym, ze lekko sie naduzylo virtual niz z tym, ze mozesz miec wyciek pamiecii
2
komentarz 28 maja 2020 przez tkz Nałogowiec (42,000 p.)
Od tego jest Valgrind. Nie ma sensu wykorzystywać virtual dla klas, które nie wykorzystują dynamicznego polimorfizmu: opakowań danych, kontenerów, klas kontrolujących współbieżność itp..

1 odpowiedź

+1 głos
odpowiedź 28 maja 2020 przez TOM_CPP Pasjonat (22,640 p.)
wybrane 5 czerwca 2020 przez Programmingc100
 
Najlepsza

Zobacz jak można ten kod napisać

  1. Bez używania zdublowanych zmiennych w klasach pochodnych.
  2. Używając czysto wirtualnej funkcji daj_glos w klasie bazowej.
  3. Z użyciem listy inicjalizacyjnej w której wywoływany jest konstruktor klasy bazowej
  4. Używając inteligentnych wskaźników uinque_ptr
  5. Dodając przeładowanie operatora << w celu czytelnego wyświetlania danych z klasy
#include <iostream>
#include <vector>
#include <memory>

using namespace std;

class Zwierze
{
public:

    Zwierze( const string& nazwa_ , const string& kolor_ , int rozmiar_ , int wiek_ ) : nazwa {nazwa_} , kolor {kolor_} , rozmiar {rozmiar_} , wiek {wiek_} {}
    virtual ~Zwierze(){}

    virtual void daj_glos() = 0;

    const string nazwa;
    string kolor;
    int rozmiar {0};
    int wiek {0};

    friend ostream& operator<<( ostream& os , const Zwierze& zwierze )
    {
        os << "Jestem " << zwierze.nazwa << " mam kolor " << zwierze.kolor << " , rozmiar = " << zwierze.rozmiar << " wiek = " << zwierze.wiek << endl;
        return os;
    }
};

class  Kot : public Zwierze
{
public:

    Kot( const string& kolor_ , int rozmiar_ , int wiek_ ) : Zwierze("Kot",kolor_,rozmiar_,wiek_) {}

    void daj_glos() override { cout << "Miau "  << endl; }
};

class  Pies : public Zwierze
{
public:

    Pies( const string& kolor_ , int rozmiar_ , int wiek_ ) : Zwierze("Pies",kolor_,rozmiar_,wiek_) {}

    void daj_glos() override { cout << "Woof " << endl; }
};

class  Krowa : public Zwierze
{
public:

    Krowa( const string& kolor_ , int rozmiar_ , int wiek_ ) : Zwierze("Krowa",kolor_,rozmiar_,wiek_) {}

    void daj_glos() override { cout << "Muuuu "  << endl; }
};

int main()
{
    vector<unique_ptr<Zwierze>> farma;

    farma.emplace_back(make_unique<Pies>("Szary",20,3));
    farma.emplace_back(make_unique<Krowa>("Brazowa",120,7));
    farma.emplace_back(make_unique<Kot>("Bialy",18,2));

    for( const auto& zwierze : farma )
    {
        cout << *zwierze;
        zwierze->daj_glos();
    }

    return 0;
}

 

1
komentarz 6 czerwca 2020 przez TOM_CPP Pasjonat (22,640 p.)

@tkz, Warto dodać, że powyższy sposób usuwania zmienia kolejność elementów w wektorze, więc nie nadaje się w sytuacji kiedy musi być ona zachowana.
 

komentarz 6 czerwca 2020 przez Programmingc100 Bywalec (2,620 p.)
Dostaje błąd że class unique_ptr<Zwierze> has no member named 'imie'. Ale klasa 'Zwierze ' ma zmienną string o nazwie imie tylko że prywatną ale jak zmieniam na publiczną to nic nie zmienia więc nie rozumiem tego błędu
1
komentarz 6 czerwca 2020 przez tkz Nałogowiec (42,000 p.)
Nie widzę zmiennej imie w jakiekolwiek klasie. Pokaż kod.
komentarz 6 czerwca 2020 przez Programmingc100 Bywalec (2,620 p.)
#include <iostream>
#include <vector>
#include <memory>

using namespace std;

class Zwierze
{

protected:
    Zwierze(const string& nazwa_, const string& imie_, unsigned rozmiar_, unsigned wiek_ )
      : nazwa {nazwa_} , imie {imie_} , rozmiar {rozmiar_} , wiek {wiek_} {}

public:
    virtual ~Zwierze() = default;

    virtual void daj_glos() const = 0;

    ostream& os(ostream& os) const {
        return os << "Jestem " << nazwa << ". Mam na imie "
          << imie << ". Rozmiar " << rozmiar
          << ". Wiek " << wiek << ".\n";
    }

private:
    const string nazwa;
    string imie;
    unsigned rozmiar;
    unsigned wiek;
};
ostream& operator<<(ostream& ost ,const Zwierze& zwierze )
{
    return zwierze.os(ost);
}
class  Kot : public Zwierze
{
public:

    Kot(const string& imie_, unsigned rozmiar_, unsigned wiek_ )
      : Zwierze("Kot", imie_, rozmiar_, wiek_) {}

    void daj_glos() const override { cout << "Miau "  << '\n'; }
};
class  Pies : public Zwierze
{
public:

    Pies(const string& imie_ , unsigned rozmiar_, unsigned wiek_ )
      : Zwierze("Pies", imie_, rozmiar_, wiek_) {}

    void daj_glos() const override { cout << "Woof " << '\n'; }
};
class  Krowa : public Zwierze
{
public:

    Krowa(const string& imie_ , unsigned rozmiar_ , unsigned wiek_ )
      : Zwierze("Krowa", imie_, rozmiar_, wiek_) {}

    void daj_glos() const override { cout << "Muuuu "  << '\n'; }
};
int main()
{
      int n;
      string name,imie;
      int wiek,rozmiar,a;
      vector<unique_ptr<Zwierze>> farma;
      cout<<"MENU: \n 1: Dodaj nowe zwierze: \n 2: Usun zwierze: \n 3: Edytuj zwierze \n 4:  Daj Glos \n 5: Wyjdz \n ";

    while(n!=5)
   {
       cin>>n;
       switch(n)
     {
           case 1:
          {
                cout<<"MENU: \n 1: Pies: \n 2: Kot: \n 3: Krowa \n 4:  Kon \n 5: Wyjdz \n ";

              while(a!=5)
             {
                 cin>>a;
              switch(a)
              {

              case 1:
                  {
                       cin.ignore();
                       cout<<"Pojda imie dla zwierzecia ktore chcesz dodac: "<<endl;
                       getline(cin,imie);
                       cout<<"Pojda rozmiar zwierzecia ktore chcesz dodac: "<<endl;
                       cin>>rozmiar;
                       cout<<"Pojda wiek zwierzecia ktore chcesz dodac: "<<endl;
                       cin>>wiek;
                       farma.emplace_back(make_unique<Pies>(imie,rozmiar,wiek));
                     break;
                  }
              case 2:
                  {
                       cin.ignore();
                       cout<<"Pojda imie dla zwierzecia ktore chcesz dodac: "<<endl;
                       getline(cin,imie);
                       cout<<"Pojda rozmiar zwierzecia ktore chcesz dodac: "<<endl;
                       cin>>rozmiar;
                       cout<<"Pojda wiek zwierzecia ktore chcesz dodac: "<<endl;
                       cin>>wiek;
                       farma.emplace_back(make_unique<Kot>(imie,rozmiar,wiek));
                    break;
                  }
                 case 3:
                  {
                        cin.ignore();
                        cout<<"Pojda imie dla zwierzecia ktore chcesz dodac: "<<endl;
                        getline(cin,imie);
                        cout<<"Pojda rozmiar zwierzecia ktore chcesz dodac: "<<endl;
                        cin>>rozmiar;
                        cout<<"Pojda wiek zwierzecia ktore chcesz dodac: "<<endl;
                        cin>>wiek;
                        farma.emplace_back(make_unique<Krowa>(imie,rozmiar,wiek));
                    break;
                  }
                 case 5:
                  {
                    break;
                  }
                }
                cout<<" 1: Pies: \n 2: Kot: \n 3: Krowa \n 4:  Kon \n 5: Wyjdz \n ";
              }

            break;
           }
           case 2:
            {
                cout<<"MENU: \n 1: Pies: \n 2: Kot: \n 3: Krowa \n 4:  Kon \n 5: Wyjdz \n ";

              while(a!=5)
             {
                 cin>>a;
              switch(a)
              {

              case 1:
                  {
                        cin.ignore();
                        cout<<"Pojda imie dla zwierzecia ktore chcesz dodac: "<<endl;
                        getline(cin,imie);
                    for(vector<unique_ptr<Zwierze>>::iterator it = farma.begin(); it!=farma.end(); ++it)
                     {
                        if(it->imie==name)
                       {
                         if(!farma.empty())
                         farma.erase(it);
                       }
                     }

                     break;
                  }
              case 2:
                  {
                    
                    break;
                  }
                 case 3:
                  {
                        
                    break;
                  }
                 case 5:
                  {
                    break;
                  }
                }
                cout<<" 1: Pies: \n 2: Kot: \n 3: Krowa \n 4:  Kon \n 5: Wyjdz \n ";
              }
                break;
            }
           case 3:
            {

                cout<<"Ktore zwierze chcesz edytowac: \n 1: Pies: \n 2: Kot: \n 3: Krowa \n 4:  Kon \n 5: Wyjdz \n ";

              while(a!=5)
             {
                 cin>>a;
              switch(a)
              {

              case 1:
                  {

                     break;
                  }
              case 2:
                  {

                    break;
                  }
                 case 3:
                  {

                    break;
                  }
                 case 5:
                  {
                    break;
                  }
                }

              }
                break;
            }
           case 4:
            {
                break;
            }
           case 5:
            {
                break;
            }

      }
      cout<<"Wybierz numer lub wyjdz: "<<endl;
   }

 

1
komentarz 7 czerwca 2020 przez tkz Nałogowiec (42,000 p.)
if (it->get()->imie == name)

Po tej zmianie się kompiluje, a no i private na public w klasie Zwierze. Może jest więcej błędów, ale nie sprawdzałem. 

Podobne pytania

0 głosów
3 odpowiedzi 2,111 wizyt
pytanie zadane 21 maja 2015 w C i C++ przez Ins0mniaC Obywatel (1,400 p.)
0 głosów
1 odpowiedź 752 wizyt
0 głosów
1 odpowiedź 366 wizyt
pytanie zadane 13 stycznia 2019 w C i C++ przez A$AP_Becari Nowicjusz (170 p.)

92,632 zapytań

141,500 odpowiedzi

319,879 komentarzy

62,013 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!

...