• 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

Cloud VPS
0 głosów
1,301 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 (195,240 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,060 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 (195,240 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,060 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,060 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,060 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,417 wizyt
pytanie zadane 21 maja 2015 w C i C++ przez Ins0mniaC Obywatel (1,400 p.)
0 głosów
1 odpowiedź 1,087 wizyt
0 głosów
1 odpowiedź 545 wizyt
pytanie zadane 13 stycznia 2019 w C i C++ przez A$AP_Becari Nowicjusz (170 p.)

93,459 zapytań

142,454 odpowiedzi

322,724 komentarzy

62,837 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

Kursy INF.02 i INF.03
...