• 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

VPS Starter Arubacloud
0 głosów
644 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,090 wizyt
pytanie zadane 21 maja 2015 w C i C++ przez Ins0mniaC Obywatel (1,400 p.)
0 głosów
1 odpowiedź 724 wizyt
0 głosów
1 odpowiedź 351 wizyt
pytanie zadane 13 stycznia 2019 w C i C++ przez A$AP_Becari Nowicjusz (170 p.)

92,452 zapytań

141,262 odpowiedzi

319,085 komentarzy

61,854 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

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 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!

...