vector wskaźników, problem z dodawaniem elementów

0

Witam

Przetrząsnąłem pół internetu szukając odp na mój problem, ale niestety nigdzie nie znalazłem nic użytecznego. Robię projekt z bibliotek STL i umyśliłem sobie zrobić program symulujący bazę danych biblioteki. Mam taki kod głównej klasy programu:

 
class CBibl
{
    static CBibl * bib;
    vector < COsoba *> uzytkownicy;
    vector < CKsiazka *> ksiazki;
    CBibl();
public:
    static CBibl * start();
    void dodajks( CKsiazka * );
    void dodajos( COsoba * );
    //(...)
}

kod klasy COsoba:

class COsoba
{
    string imie;
    string nazwisko;
    CKsiazka * ks[ limit ];
public:
    COsoba( string a, string b )
        : imie( a )
        , nazwisko( b )
    { ks[ 0 ] = 0; }
    //(...)
}
 

Problem polega na tym, że próbując dodać nowy wskaźnik do vectora poprzez metodę:

 
void CBibl::dodajos( COsoba * a )
{
    uzytkownicy.push_back( a );
}

Wywoływaną w sposób:

dodajos( new COsoba( a, b ) )

Program wyrzuca błąd "Unhandled exception at 0x00fe7c99 in stl.exe: 0xC0000005: Access violation reading location 0x0000001c." Nie rozumiem, jak w tak prostym tworze jak vector wskaźników występować błędy pamięci. W żaden sposób nie próbuję się odwołać do miejsc na które wskazują przechowywane wskaźniki więc nawet jeśli błędy byłyby w samych obiektach to chyba nie powinno mieć żadnego znaczenia, jako, że przechowywane są w zupełnie innym miejscu pamięci? Nie ma znaczenia czy dodaję obiekt klasy CKsiazka, czy COsoba. Próbowałem nawet zmienić vector na vector obiektów - to także nie uczyniło żadnej różnicy. Obiekty tworzone i przekazywane do funkcji są poprawnie.

Po wysypaniu programu Visual kieruje mnie do funkcji z vector.h:

 bool _Inside(const _Ty *_Ptr) const
		{	// test if _Ptr points inside vector
		return (_Ptr < this->_Mylast && this->_Myfirst <= _Ptr);
		}
0

A powiedz mi po jaką cholerę Ci w tym programie jakikolwiek wskaźnik jeżeli używasz tam std::vectora?
Bjarne Stroustrup mówi, że ludzie tak piszą, bo wydaje się im, że tak jest cool

0

Poza tym dlaczego konstruktor CBibl(){} masz w private?
Zmień to i powinno się kompilować.

0

Wskaźniki są po to, żeby móc używać polimorfizmu, po klasie COsoba dziedziczą inne, bez tego musiałbym mieć osobny vector na każdą klasę pochodną. Konstruktor jest w private ponieważ CBibl to główny obiekt programu i występuje tylko raz, zapobiega to tworzeniu jego kolejnych instancji. Nie ma to nic wspólnego z opisywanym problemem, obiekt CBibl jest tworzony poprawnie, błędy występują w push_back.

Poza tym, jak napisałem, w pewnym momencie zmieniłem vector wskaźników na vector obiektów i błąd występował dalej...

0

Możesz wkleić cały kod? Trochę ciężko mi mówić nie widząc całości..

0

Nie ma problemów z kompilacją tylko z wykonaniem programu. Całego kodu nie wkleję bo nie ma sensu, nie jest wykorzystywany, plik main wygląda tak:

 
#include "bib.h"
#include <iostream>

void dodajks();
void dodajos();
void menu();

CBibl* BIBL = CBibl::start();

int main()
{
	menu();
	short a;
	cin >> a;
	switch(a)
	{
	case 1:
		dodajks();
		break;
	case 2:
		break;
	case 3:
                dodajos();
		break;
	case 4:
		break;
	case 5:
		break;
	case 6:
		break;
	case 7:
		BIBL->wypiszos();
		break;
	case 8:
		BIBL->wypiszks();
		break;
	}
	delete BIBL;
	system("PAUSE");
	return 0;
}

void menu()
{
	cout << "\tMENU:\n"
		 << "1: Dodaj ksiazke do zbioru.\n"
		 << "2: Usun ksiazke ze zbioru.\n"
		 << "3: Dodaj uzytkownika.\n"
		 << "4: Usun uzytkownika.\n"
		 << "5: Wypozycz ksiazke.\n"
		 << "6: Przyjmij ksiazke.\n"
		 << "7: Wypisz uzytkownikow.\n"
		 << "8: Wypisz ksiegozbior.\n";
}

void dodajks()
{
	string a, b;
	unsigned long c;
	cout << "Podaj tytul: ";
	cin >> a;
	cout << "Podaj autora: ";
	cin >> b;
	cout << "Podaj numer ISBN: ";
	cin >> c;
	//CKsiazka* K = new CKsiazka(a, b, c);
	BIBL->dodajks(new CKsiazka(a, b, c));
}

void dodajos()
{
	string a, b;
	unsigned long c;
	cout << "Podaj imie: ";
	cin >> a;
	cout << "Podaj nazwisko: ";
	cin >> b;
	cout << "Jesli jest studentem podaj nr indeksu (jesli nie, wpisz 0): ";
	cin >> c;
	if(c)
		BIBL->dodajos(new CStudent(a, b, c));
	else
		BIBL->dodajos(new COsoba(a, b));
}

Funkcję dodajos pokazałem wcześniej, funkcja dodajks wygląda analogicznie. Program nie jest skończony jak widać, więc nie za bardzo ma się co psuć na tym etapie...

Funkcja CBibl:

 
CBibl* CBibl::start()
{
	if(!bib)
		CBibl();
	return bib;
}
CBibl::CBibl()
{
	bib=this;
}
 
0
CBibl* CBibl::start()
{
        if(!bib)
                CBibl();
        return bib;
}

po co wywołujesz konstruktor ręcznie i gdzie bib jest zerowane skoro konstruktor jest prywatny?

0
hmm napisał(a)
CBibl* CBibl::start()
{
        if(!bib)
                CBibl();
        return bib;
}

po co wywołujesz konstruktor ręcznie i gdzie bib jest zerowane skoro konstruktor jest prywatny?

bez pytania o zerowanie bo teraz zauważyłem, że to pole statyczne. Czy to ma być jakiś pseudo singleton?

0

Tak, to singleton, to główna klasa obsługująca cały program.

0

Poczytaj o Singletonie..

 //Definicja
 class singleton
 {
  private:
        singleton() {}
        singleton(const singleton &);
        singleton& operator=(const singleton&);
  public:
        std::string method() { return "singleton pattern"; }
        static singleton& getInstance()
        {
          //Inicjalizacja statycznego obiektu.
          //Obiekt zostanie utworzony przy pierwszym wywołaniu tej metody
          //i tylko wtedy nastąpi inicjalizacja przy pomocy konstruktora.
          //Każde następne wywołanie jedynie zwróci referencję tego obiektu.
          static singleton instance;
          return instance;
        }
 };
 
 //Uzycie
 std::cout << singleton::getInstance().method();
0

Masz rację, problem jest w tym, że CBibl jest singletonem, ale szczerze mówiąc to nie mam pojęcia co zrobiłem źle. Cała koncepcja nie jest trudna i wydaje mi się, że dobrze ją rozumiem. No ale widać będę musiał ją jeszcze raz przerobić. Anyway dzięki za pomoc.

0
#include <iostream>
#include <string>
#include <vector>

class COsoba{
    std::string imie;
    std::string nazwisko;
public:
    COsoba(std::string a,std::string b):imie(a),nazwisko(b){}
    std::string getname(){
        return nazwisko+" "+imie;
    }
};
class singleton{
    singleton(){}
    singleton(const singleton &);
    singleton& operator=(const singleton&);
    std::vector<COsoba*>uzytkownicy;
public:
    static singleton& getInstance(){
      static singleton instance;
      return instance;
    }
    void dodajos(COsoba*n){
        uzytkownicy.push_back(n);
    }
    void wypisz(){
        for(int i=0;i<uzytkownicy.size();i++){
            std::cout<<uzytkownicy[i]->getname()<<"\n";
        }
    }
};
int main(){
    singleton::getInstance().dodajos(new COsoba("Pierwszy","X"));
    singleton::getInstance().dodajos(new COsoba("Drugi","X"));
    singleton::getInstance().dodajos(new COsoba("Trzeci","X"));
    singleton::getInstance().wypisz();
    return 0;
}

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