Dodawanie obiektów klasy do vector 'a - funkcja

0

Mam stworzony vector, który przechowuje obiekty danej klasy. Chcę stworzyć funkcję, która pozwala na dodawanie elementów do tego vectora. Poniżej kod funkcji, który nie działa i to jest dla mnie zrozumiałe (funkcja ta nie ma "dostępu" do vectora). Ale nie mam pomysłu na rozwiązanie problemu.

Funkcja Dodaj_ksiazke

void Ksiazka::Dodaj_ksiazke()
{
    bool Nokladka;
    short Nilosc_sztuk, Nid, Nilosc_stron;
    float Ncena;
    string Ntytul, Nautor, Ngatunek, Nwydawnictwo;

    cout << "Podaj dane." << endl;
    cout << "Tytul: "; cin >> Ntytul;
    cout << "Autor: "; cin >> Nautor;
    cout << "Gatunek: "; cin >> Ngatunek;
    cout << "Wydawnictwo: "; cin >> Nwydawnictwo;
    cout << "Ilosc stron: "; cin >> Nilosc_stron;
    cout << "Okladka: "; cin >> Nokladka;
    cout << "Cena: "; cin >> Ncena;
    cout << "Ilosc sztuk: "; cin >> Nilosc_sztuk;

    ksiazki.push_back(Ksiazka(Ntytul,Nautor,Ngatunek,Nwydawnictwo,Nilosc_sztuk,Nid,
                    Nilosc_stron,Ncena,Nokladka));
}

Nie wiem co jest bardziej poprawne, deklaracja vectora wewnątrz main() czy poza ciałem funkcji ?

Funkcja main

int main()
{
    vector<Ksiazka> ksiazki;
    getch();
    return 0;
}
0

Kombinujesz strasznie. Zrób z dodaj_ksiazke konstruktor i go wpychaj do wektora.

0

Rzeczywiście można :)

 
Ksiazka :: Ksiazka(
    string Ntytul,
    string Nautor,
    string Ngatunek,
    string Nwydawnictwo,
    //short Ndata_wydania[7],
    //short Nisbn[12],
    short Nilosc_sztuk,
    short Nid,
    short Nilosc_stron,
    float Ncena,
    bool Nokladka
):ElementKolekcji(
        Ntytul,
        Nautor,
        Ngatunek,
        //short Ndata_wypozyczenia[7],
        //short Ntermin_zwrotu[7],
        //short Ndata_wydania[7],
        Ncena,
        Nilosc_sztuk
    )
    {

    cout << "Podaj dane." << endl;
    cout << "Tytul: "; cin >> Ntytul;
    cout << "Autor: "; cin >> Nautor;
    cout << "Gatunek: "; cin >> Ngatunek;
    cout << "Wydawnictwo: "; cin >> Nwydawnictwo;
    cout << "Ilosc stron: "; cin >> Nilosc_stron;
    cout << "Okladka: "; cin >> Nokladka;
    cout << "Cena: "; cin >> Ncena;
    cout << "Ilosc sztuk: "; cin >> Nilosc_sztuk;

    tytul=Ntytul;
    autor=Nautor;
    gatunek=Ngatunek;
    wydawnictwo=Nwydawnictwo;
    //data_wydania=Ndata_wydania[7];
    //isbn[12]=Nisbn[12];
    ilosc_sztuk=Nilosc_sztuk;
    id=Nid;
    ilosc_stron=Nilosc_stron;
    cena=Ncena;
    okladka=Nokladka;

    ksiazki.push_back(Ntytul,Nautor,Ngatunek,Nwydawnictwo,Nilosc_sztuk,Nid,
    Nilosc_stron,Ncena,Nokladka);
    
    }

Tylko takie coś nie zadziała. Problem mam z "wsadzaniem" do vectora.

1

...

class Foo {
private:
  int m_boo;
public:
  Foo() {
    cin >> m_boo;
  }
};

//...

vector<Foo> vec;
vec.push_back(Foo());

Lub jeśli nie chcesz zaśmiecać sobie konstruktorów (bo to nie jest dobry pomysł to co pokazałem) i do tego zrobić to w miarę ładny sposób bez przeciążania operatorów to można tak:

class Foo {
private:
  int m_boo;
public:
  static Foo/*&&*/ load_from_stream(istream& is) { ///< jeśli używasz C++11 to usuń tutaj komentarz
    is >> m_boo;
  }
};

//...

vector<Foo> vec;
vec.push_back(Foo::load_from_stream(cin));
1

Oddziel interakcję z użytkownikiem (te wszystkie cin'y i cout'y) od klasy Ksiazka (Ksiazka ma być odpowiedzialna za przechowywanie danych o książkach a nie za gadanie z użytkownikiem), zrób do tego osobną funkcję gdzieś obok main.

Ksiazka Wczytaj_ksiazke()
{
    bool Nokladka;
    short Nilosc_sztuk, Nid, Nilosc_stron;
    float Ncena;
    string Ntytul, Nautor, Ngatunek, Nwydawnictwo;
 
    cout << "Podaj dane." << endl;
    cout << "Tytul: "; cin >> Ntytul;
    cout << "Autor: "; cin >> Nautor;
    cout << "Gatunek: "; cin >> Ngatunek;
    cout << "Wydawnictwo: "; cin >> Nwydawnictwo;
    cout << "Ilosc stron: "; cin >> Nilosc_stron;
    cout << "Okladka: "; cin >> Nokladka;
    cout << "Cena: "; cin >> Ncena;
    cout << "Ilosc sztuk: "; cin >> Nilosc_sztuk;
 
    return Ksiazka(Ntytul,Nautor,Ngatunek,Nwydawnictwo,Nilosc_sztuk,Nid,
                    Nilosc_stron,Ncena,Nokladka));
}

int main()
{
    vector<Ksiazka> ksiazki;
    ksiazki.push_back(Wczytaj_ksiazke());
}
0

Dzięki za odpowiedzi. Wiedziałem, że mogę zrobić tak, jak pokazał @adf88 . Myślałem, że można to zrobić w ten sposób, że mam funkcję/-e, wywołuje w main() i szafa gra. Jedynie zadeklarowany mam vector<foo> vec. Ale chyba jednak aż tak "wyciągnąć" poza main() się tego wszystkiego nie da i trzeba w main() użyć push_back.

(edycja)

Rozumiem, czyli powinienem oddzielić klasy od interfejsu użytkownika ? Tak to się chyba nazywa...

0

@adf88 ale return w ten sposób chyba nie może zwrócić wielu wartości ? Tak można chyba w Pythonie, choć nie wiem, nie programowałem w nim. W jaki sposób w C++ mogę zwrócić wiele wartości ? Wskaźniki, referencje ?

1

Zgadza się. Ale gdzie ci to w ogóle potrzebne?

Natomiast jeśli chodzi o push_back'i to możesz też opakować w klasy. Możesz np. zrobić klasę księgozbioru reprezentującą zbiór książek.

Możesz też przydzielić jeden księgozbiór na sztywno do programu. Rozwiązanie mniej uniwersalne, ale prostsze:

class Ksiazka {
private:
    static vector<Ksiazka*> zbior;

public:
    static Ksiazka *Dodaj()
    {
        Ksiazka::zbior.push_back(new Ksiazka);
        return Ksiazka::zbior.back();
    }
};

int main()
{
    Ksiazka *ksiazka = Ksiazka::Dodaj();
    Wczytaj_ksiazke(ksiazka);
}

void Wczytaj_ksiazke(Ksiazka *ksiazka)
{
    cout << "Podaj dane." << endl;
    cout << "Tytul: "; cin >> ksiazka->tytul;
    // ...
}
0

Dzięki. W sumie teraz wiem, do czego konkretnie można zastosować static, ale kod i tak będę musiał napisać od początku jeszcze raz, bo jak teraz patrzę, to nie bardzo mi się to podoba wszystko.

@vpiotr

Mam pytanie do twojego komentarza. Przeczytałem o co chodzi z http://en.wikipedia.org/wiki/Method_chaining . Rozumiem, że zamiast używania konstruktora do ustawiania odpowiednich atrybutów obiektu, używam 'setterów'. Jak wygląda wtedy konstruktor ? Wywołuje w nim odpowiednie metody 'set' ?

0
cichociemny napisał(a):

Mam pytanie do twojego komentarza. Przeczytałem o co chodzi z http://en.wikipedia.org/wiki/Method_chaining . Rozumiem, że zamiast używania konstruktora do ustawiania odpowiednich atrybutów obiektu, używam 'setterów'. Jak wygląda wtedy konstruktor ? Wywołuje w nim odpowiednie metody 'set' ?


class MojaKlasa {
public:
  enum Models {
     MDL_NULL,
     MDL_VAN
  };

  enum Colors {
     COL_NULL,
     COL_BLACK
  };

   MojaKlasa(): m_model(MDL_NULL), m_color(COL_NULL) {}
   MojaKlasa &setModel(int model) { m_model = model; return *this; }
   int getModel() { return m_model; }
   MojaKlasa &setColor(int color) { m_color = color; return *this; } 
   //... 
private:
   int m_model;
   int m_color;
};  

MojaKlasa foo(parametry) {
  return MojaKlasa().setModel(MDL_VAN).setColor(COL_BLACK);
}

Przy takim podejściu:

  • nie musisz pamiętać kolejności parametrów w konstruktorze (chociaż w nowoczesnym IDE masz podpowiedź)
  • możesz sobie wybrać które parametry wypełniasz - możesz pominąć nie tylko te od końca ale także w środku
0

Witam
Przepraszam, że odkopuję ale nie znalazłem rozwiązania a nie chcę zakładać nowego tematu skoro zagadnienie podobne.
Mam klasę która ma dwa pola.
Utworzyłem kontener tej klasy i wypełniłem go danymi:

list<Sygnal> sygnal;
    Sygnal temp;
    fstream syg;
    syg.open("dane.txt", ios::in);
    if(!syg.is_open())
        return 0;
    
    while(!syg.eof())
    {
        syg >> temp.time;
        //cout << temp.time << endl;
        syg >> temp.value;
        //cout << temp.value << endl;
        sygnal.push_back(temp);
    }
    
    for(list<Sygnal>::iterator iter=sygnal.begin(); iter!=sygnal.end(); iter++)
    {
        cout<< *iter <<endl;
    }

Ostatnia pętla nie działa. W jaki sposób dostać się do konkretnego elementu? Chodzi o pola time i value oczywiście
Pozdr

0

Do wypisania wystarczyło przeciążyć operator <<, ale pytanie pozostaje nadal aktualne... jak np zmienić wartość value dla konkretnego obiektu?

0

iter->time, iter->value?

0

Dzięki wielki! Zadziałało.
Pojawił się kolejny problem; mianowicie w jaki sposób utworzyć kontener klasy pochodnej która dziedziczy z klasy bazowej? Klasa pochodna ma konstruktor który ustawia jedną wartość. Nie mogę po prosty zrobić tak:

vector<KlasaPochodna*> vec(10); 

Bo to utworzy mi kontener o pojemności "10";
Próbowałem tak ale wyskakują błędy:

vector<Baza*> bloczek;
bloczek.push_back(new Pochodna(10));
Undefined symbols for architecture x86_64:
  "typeinfo for Baza", referenced from:
      typeinfo for Pochodna in main.o
  "vtable for Baza", referenced from:
      Baza::Baza() in main.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Jak na to zaradzić?

zamiana znacznika <quote> na <code class="none"> - @furious programming

1 użytkowników online, w tym zalogowanych: 0, gości: 1