Dodanie obiektu do Listy w konstruktorze


(Trance) #1

Mam proble mianowicie próba wrzucenia obiektu do Listy konczy się błędem:

kod

class Lot{

        string miejsce_odlotu;

        string miejsce_przylotu;

        int wolne_miejsca;

        int cena; 

        static listbaza; 

        public:

        Lot(){};

        Lot(string o,string m,int w,int c)

                                  {miejsce_odlotu=o;

                                   miejsce_przylotu=m;

                                   wolne_miejsca=w;

                                    cena=c;

                                   baza.push_Back(this)

                                     }  

     // static void dodaj(Lot p){baza.push_back(p);} albo tak                



        };

błąd z Dev'a

[Linker error] undefined reference to `Lot::baza' 

  ld returned 1 exit status 

 D:\Programy\Dev-Cpp\Makefile.win [Build Error] [Project1.exe] Error 1

W main jest obiekt tej klasy...

C o jest nie tak :?: :?: :?:


([alex]) #2

po deklaracji klasy dodaj:

list Lot::baza;

EDIT:

Absolutna racja, tylko że nie chciało mi się wymieniać wszystkich wad podanego kodu, wymiana wszystkich wad była by dłuższa niż podany kod, więc podałem najszybsze rozwiązanie. Fiołek pomyśl, patrząc na podany kod masz przepuszczenie że autor podzielił to na kod i pliki nagłówkowe?


(Fiołek) #3

Nie po deklaracji klasy, tylko w pliku źródłowym bo inaczej linker dostanie multiple definition :wink:

Masz do tego literówkę w push_ B ack, błąd w parametrze(wskaźnik zamiast referencji) i brak średnika


(Trance) #4

ja jednak chciałbym :? poznać te wady. . .


([alex]) #5

W skrócie:

  1. Nie ma sensu przy każdym połączeniu trzymać miejsca odlotu i przylotu w postaci napisu, prowadzi to do sytuacji że będą miejsca: "warszawa", "Warszawa", "w-wa"; Najlepiej zrobić osobną tablicę z miejscami, a na liście trzymać jedynie wskaźnik na miejsca przylotu/odlotu.

  2. W miarę możliwości w konstruktorach C++ należy używać listy inicjalizacyjnej.

  3. Brak destruktora usuwającego Lot z listy

  4. Pomysł na jedna jedyna listę nie jest zbyt udany, warto zrobić klasę Lista_Lotow i do niej dodawać Lot'y


(Trance) #6

a więc tak zacznijmy od tego ze klasa nie była jeszcze skończona,wystapił problem więc wrzuciłem to co wtedy miałem napisane,

  1. chyba nie jest jakimś większym problemem napisanie funkcji która zmienia wielkość liter w słowie np. na same duże (problem typu: Waszawa,warszawa,waRSZawa więc nie istnieje)

  2. Jeżeli nie jest to statyczny składnik to chyba nie jest błędem umieszczenie przypisań w ciele konstruktora (zamiast na liście inicjalizacyjnej)

  3. Funkcję już dopisałem

4 Nie bardzo widzę sens tworzenia nowej klasy skoro wszystko można "załatwić" w tej.


([alex]) #7
  1. Nie wymyślisz algorytmu stwierdzającego że "wa-wa" jest tym samym co "warszawa".

  2. Może się okazać błędem w niektórych przypadkach.

  3. Ma być destruktor a nie funkcja.

  4. Zastanów się co zrobi funkcja:

    Lot Szukaj(Lot X)

    {

    dla wszystkich L z Lot::baza

     {
    
      if(X.miejsce_przylotu==L.miejsce_przylotu) return L;
    
     }

    return Lot("","",0,0);

    }

przy wywołaniu:

Lot L=Szukaj(Lot("","warszawa",0,0));

(Trance) #8

  1. Nie popadajmy w skrajności 2. Można prosić jakiś przykład ( pytam serio, w jakich przypadkach przypisanie wartości niestatycznemu składnikowi w ciele konstruktora może wywalić błąd, a zadziała przypisanie w liście inijaliz.) 3. Tutaj też mam wątpliwości, nie rezerwowaliśmy pamięci przez new więc dlaczego obowiązkowo musi być destruktor, w funkcji można dodać obiekt do listy - w funkcji można go również usunąć. 4 Co do funkcji,( nie wiem czy dobrze to wykombinowałem) co jeżeli będzie więcej obiektów spełniających warunek

    (X.miejsce_przylotu==L.miejsce_przylotu)

w funkcji zwrócony tylko zostanie pierwszy, co z pozostałymi. . . .


([alex]) #9
  1. Nie ma sensu przy każdym połączeniu trzymać miejsca odlotu i przylotu w postaci napisu, wystarczy wskaźnik.

2.

// spróbuj zrobić konstruktor bez listy inicjalizacyjnej

class X { int &x; X(int &x):x(x) {} };

int p=0;

X x(p);

Ale to nie jedyna powód, uruchom ten kod :wink:

class dane

  {

   int d;

   public:

   dane():d(0) { cout<<"konstruktor domyslny"<
   dane(int d):d(d) { cout<<"konstruktor parametryzowany"<
   dane(const dane &d):d(d.d) { cout<<"konstruktor kopiujacy"<
   ~dane() { cout<<"destruktor"<
   dane &operator=(const dane &d) { cout<<"operator przypisania"<
  };


class LikeLot

  {

   dane d;

   public:

   LikeLot(dane p) { d=p; }

  };


class LikeGood

  {

   dane d;

   public:

   LikeGood(const dane &p):d(p) {}

  };


int main()

  {

   dane d(0);

   cout<<"LikeLot"<
   LikeLot x(d);

   cout<<"--------"<
   cout<<"LikeGood"<
   LikeGood y(d);

   cout<<"--------"<
   cin.get();

   return 0;

  }

Zauważ że klasa string ma wszystkie konstrukcje które ma klasa dane.

  1. "... w funkcji można dodać obiekt do listy - w funkcji można go również usunąć ...", zgadza się tylko że ty dodajesz do listy w konstruktorze.

  2. Chyba nie zrozumiałeś, ten przykład dołoży dwa Lot'a do listy :lol: