Skocz do zawartości

Zarchiwizowany

Ten temat jest archiwizowany i nie można dodawać nowych odpowiedzi.

dmn

Rozwiązany: [C++] Lista połączona, przekazanie stringa i przedwczesne wywolanie destruktora

Polecane posty

Witam wszystkich !!

Mam taki mały programik, ktory tworzy liste ksiazek wpisywanych przez uzytkownika i sortuje wg podanego numeru tytulu.

Co prawda kompiluje sie, jednak przy dodawaniu obiektu 'ksiazka' na sterte zostaje on zniszczony... w nastepstwie program sie wykrzacza...

Z tego co dotychczas zdazylem sie nauczyc to obiekty niszczone sa po zakonczeniu programu a nie w trakcie. Dlaczego wiec przed zakonczeniem pętli wywoluje sie destruktor?

Pomogłby ktoś rozwiązać ten problem?

a program wyglada tak:

#include <iostream>
#include <string>

using namespace std;
enum {Wieksze, Mniejsze, Rowne};

// klasa przechowujaca dane o ksiazce (tytul , nr na liscie):
class Ksiazka
{
      public:
             Ksiazka(int, string);
          //   Ksiazka(int);
             ~Ksiazka(){};
             void Pokaz();
             int Porownaj(Ksiazka &);
             int PodajNr() { return Nr; }
             string PodajTytul() { return Tytul; }
      private:
              int Nr;
              string Tytul;
};

Ksiazka::Ksiazka(int nr, string tytul):
                     Nr(nr),
                     Tytul(tytul)
{
cout << "tworze ksiazke nr " << nr << endl;
//dlugosc = strlen(tytul);
}

/*Ksiazka::Ksiazka(int nr)
{
cout << "zapisuje ksiazke nr " << nr << endl;
Nr = nr;
} */


void Ksiazka::Pokaz()
{
  cout << Nr << ". \"" << Tytul << "\"" << endl;
  //cout << Nr << endl;
}

int Ksiazka::Porownaj(Ksiazka & nowyTytul)
{
    cout << "porownuje ksiazke nr " << Nr << " z ksiazka nr " << nowyTytul.PodajNr() << endl;
    if (Nr > nowyTytul.PodajNr())
       return Wieksze;
    if (Nr < nowyTytul.PodajNr())
       return Mniejsze;
}

//***************************************klasa bazowa

class Wezel
{
      public:
             Wezel(){ cout << "konstruktor klasy Wezel\n"; }
             virtual ~Wezel(){ cout << "destruktor klasy Wezel\n"; }
             virtual Wezel* Dodaj(Ksiazka*tytulKs)=0;
             virtual void Pokaz()=0;
      private:
};

//*********KLASA: WEZEL WEWNETRZNY****************

class WezelWewn : public Wezel
{
      public:
             WezelWewn(Ksiazka*kniga, Wezel*wezel);
             virtual ~WezelWewn(){ cout << "destruktor klasy WezelWewn...\n"; }
             virtual Wezel* Dodaj(Ksiazka*tytulKs);
             virtual void Pokaz() { mojTytul->Pokaz(); next->Pokaz(); }

      private:
              Wezel * next;
              Ksiazka * mojTytul;
};

WezelWewn::WezelWewn(Ksiazka*kniga, Wezel*wezel):
                                    next(wezel),
                                    mojTytul(kniga)
{
cout << "konstruktor klasy WezelWewn...\n";
}

Wezel * WezelWewn::Dodaj(Ksiazka*pKsiazka)
{
      cout << "Uruchamiam funkcje WezelWewn::Dodaj()\n";
      int wynik = mojTytul->Porownaj(*pKsiazka);
      switch (wynik)
      {
             case Rowne:
             case Wieksze:
                  {
                   WezelWewn * nowyWezel = new WezelWewn(pKsiazka, this);
                   cout << "Tworze nowy WezelWewn gdyz nowa pozycja jest wyzej na liscie\n";
                   return  nowyWezel;
                  }
             case Mniejsze:
                  {
                   cout << "Przekazuje ksiazke do kolejnego WezlaWewn. gdyz nowa pozycja jest nizej na liscie\n";
                   next = next->Dodaj(pKsiazka);
                   return this;
                  }
      return this;
      }
}

//**************KLASA: WEZEL OGONA:****************************

class WezelOgona : public Wezel
{
      public:
             WezelOgona(){cout << "konstruktor klasy WezelOgona\n";}
             virtual ~WezelOgona(){cout << "destruktor klasy WezelOgona\n";}
             virtual Wezel * Dodaj(Ksiazka*tytulKs);
             virtual void Pokaz(){}
};

Wezel * WezelOgona::Dodaj(Ksiazka*tytulKs)
{
  WezelWewn * nowyWezel = new WezelWewn(tytulKs, this);
  return  nowyWezel;
}

//************KLASA: WEZEL GLOWY:*********************

class WezelGlowy : public Wezel
{
      public:
             WezelGlowy();
             virtual ~WezelGlowy(){ delete next; }
             virtual Wezel * Dodaj(Ksiazka*pKsiazka);
             virtual void Pokaz();
      protected:
              Wezel * next;
};

WezelGlowy::WezelGlowy()
{
cout << "konstruktor klasy WezelGlowy\n";
next = new WezelOgona;
}

Wezel * WezelGlowy::Dodaj(Ksiazka*pKsiazka)
{
      cout << "Uruchamiam funkcje WezelGlowy::Dodaj()\n";
      next = next->Dodaj(pKsiazka);
}

void WezelGlowy::Pokaz()
{
     next->Pokaz();
}

//***************************************


class ListaKsiazek
{
      public:
             ListaKsiazek(){ cout << "konstruktor klasy ListaKsiazek\n"; pHead = new WezelGlowy; }
             ~ListaKsiazek(){ delete pHead; }
             void Pokaz() { pHead->Pokaz(); }
             virtual Ksiazka Dodaj(Ksiazka*pKsiazka);
      private:
              WezelGlowy * pHead;
};

Ksiazka ListaKsiazek::Dodaj(Ksiazka*pKsiazka)
{
        cout << "Uruchamiam funkcje ListaKsiazek::Dodaj()\n";
        pHead->Dodaj(pKsiazka);
}

// *************************************

int main()
{
    Ksiazka * pKsiazka;
    int choice;
    int nr;
    ListaKsiazek LK;
    string bufor;
    while(choice!=0)
    {
            cout << "(1)Wprowadz nowa ksiazke\n(2)Wyswietl liste wprowadzonych\n(0)Wyjdz\n";
            cin >> choice;
            switch (choice)
            {      
                   case 1:
                        {
                         cout << "nr ksiazki?\n";
                         cin >> nr;
                         cout << "\ntytul?";
                         cin >> bufor;
                         pKsiazka = new Ksiazka(nr, bufor); //w ubozszej wersji z konstruktorem Ksiazka(nr) program sprawuje sie dobrze
                        
                         LK.Dodaj(pKsiazka);
                         break;
                        }
                   case 2:
                        {
                         LK.Pokaz();
                         break;
                        }
                   case 0: break;
                   default: cout << "Nie ma takiej opcji;)\n";
                   break;
            if (!choice)
            break;
            }
    }
    return 0;
}

Link do komentarza
Udostępnij na innych stronach

Ja ten kod sprawdzalem pod Borland C++ Builderem i dzialalo dobrze.

Pod DevC++ (stary, z czasow pierwszego/drugiego roku studiow) wywalalo mi naruszenie praw dostepu (blad segmentacji) przy uruchamianiu destrktora podczas wychodzenia z tej funkcji:

Ksiazka ListaKsiazek::Dodaj(Ksiazka*pKsiazka)
{
        cout << "Uruchamiam funkcje ListaKsiazek::Dodaj()\n";
        pHead->Dodaj(pKsiazka);
}

W ogole czemu tu ten destruktor jest odpalany?

Link do komentarza
Udostępnij na innych stronach

Po pierwsze jakiego kompilatora używasz? Rzeczy, które można wychwycić od razu to:

Ksiazka ListaKsiazek::Dodaj(Ksiazka*pKsiazka)
{
        cout << "Uruchamiam funkcje ListaKsiazek::Dodaj()\n";
        pHead->Dodaj(pKsiazka);
}

Ta funkcja nic nie zwraca i z tego co widzę nie powinna, więc jej typ należy zmienić na void.

Dalej

Wezel * WezelGlowy::Dodaj(Ksiazka*pKsiazka)
{
      cout << "Uruchamiam funkcje WezelGlowy::Dodaj()\n";
      next = next->Dodaj(pKsiazka);
}

Podobnie jak poprzednio ta funkcja nic nie zwraca, a powinna zdaje się zwracać obiekt typu Wezel. Poprawiłbym to tak:

Wezel * WezelGlowy::Dodaj(Ksiazka*pKsiazka)
{
      cout << "Uruchamiam funkcje WezelGlowy::Dodaj()\n";
      next = next->Dodaj(pKsiazka);
      return next;
}

Nanieś te poprawki i zobacz co się będzie wtedy działo. Dziwne, że kompilator nie wywalił błędu. Problem jest najprawdopodobniej związany z drugą rzeczą, bo tego węzła potrzebujesz w programie, a go nie ma, czyli masz odwołanie do obiektu, który nie istnieje.

Link do komentarza
Udostępnij na innych stronach

Gość
Temat jest zablokowany i nie można w nim pisać.


  • Kto przegląda   0 użytkowników

    • Brak zalogowanych użytkowników przeglądających tę stronę.
×
×
  • Utwórz nowe...