kt1117 Opublikowano 11 Marca 2011 Opublikowano 11 Marca 2011 Ostatnio uczę się obiektowości w C++ i napisałem program, który losuje liczby nie powtarzając się w obiektowości. I napotkałem dziwną sytuację. Zrobiłem konstruktor, tam wyzerowałem wszystkie zmienne, wypytałem się użytkownika o liczby i wywołałem inną metodę. W tej metodzie odwołałem się zmiennych, które przypisałem w konstruktorze, pytając się usera o liczby. I tu patrzę, a metoda wywala mi wartości z kosmosu, znaczy nie wyzerowana. I tu moje pytanie, jaki zakres ma zmienna w klasie?
kt1117 Opublikowano 11 Marca 2011 Autor Opublikowano 11 Marca 2011 #include <iostream> #include <cstdlib> #include <ctime> using namespace std; class losowanie { int wylosowane[8]; int podane[10]; int a; int b; public: void wylosowywanie(); losowanie(); ~losowanie(); }; losowanie::losowanie() { srand(time(0)); a=0; b=0; losowanie::wylosowywanie(); }; void losowanie::wylosowywanie() { cout<<"Podaj 10 liczb: "<<endl; cin>>podane[0]>>podane[1]>>podane[2]>>podane[3]>>podane[4]>>podane[5]>>podane[6]>>podane[7]>>podane[8]>>podane[9]; do { do { a=((rand())%11)-1; a=losowanie::podane[a]; } while (a==wylosowane[0] or a==wylosowane[1] or a==wylosowane[2] or a==wylosowane[3] or a==wylosowane[4] or a==wylosowane[5] or a==wylosowane[6] or a==wylosowane[7]); wylosowane[b]=a; b++; } while (b<10); }; losowanie::~losowanie() { cout<<"Liczby to:"<<wylosowane[0]<<", "<<wylosowane[1]<<", "<<wylosowane[2]<<", "<<wylosowane[3]<<", "<<wylosowane[4]<<", "<<wylosowane[5]<<", "<<wylosowane[6]<<", "<<wylosowane[7]<<"."<<endl; }; int main() { losowanie::losowanie(); return 0; } Ten kod działa, zaraz dam ten poprzedni, tylko muszę go odtworzyć. E: Ten dziwny: #include <iostream> #include <cstdlib> #include <ctime> using namespace std; class losowanie { int wylosowane[8]; int podane[10]; int a; int b; public: void wylosowywanie(); losowanie(); ~losowanie(); }; losowanie::losowanie() { srand(time(0)); a=0; b=0; int wylosowane[8]={0,0,0,0,0,0,0,0}; int podane[10]={0,0,0,0,0,0,0,0,0,0}; cout<<"Podaj 10 liczb: "; cin>>podane[0]>>podane[1]>>podane[2]>>podane[3]>>podane[4]>>podane[5]>>podane[6]>>podane[7]>>podane[8]>>podane[9]; losowanie::wylosowywanie(); }; void losowanie::wylosowywanie() { do { do { a=((rand())%11)-1; a=losowanie::podane[a]; } while (a==wylosowane[0] or a==wylosowane[1] or a==wylosowane[2] or a==wylosowane[3] or a==wylosowane[4] or a==wylosowane[5] or a==wylosowane[6] or a==wylosowane[7]); wylosowane[b]=a; b++; } while (b<10); }; losowanie::~losowanie() { cout<<"Liczby to:"<<wylosowane[0]<<", "<<wylosowane[1]<<", "<<wylosowane[2]<<", "<<wylosowane[3]<<", "<<wylosowane[4]<<", "<<wylosowane[5]<<", "<<wylosowane[6]<<", "<<wylosowane[7]<<"."<<endl; }; int main() { losowanie * obiekt=new losowanie; delete obiekt; return 0; } I ten, który według mnie powinien działać a wywala błąd: w\losowanie\main.cpp||In constructor 'losowanie::losowanie()':| w\losowanie\main.cpp|24|warning: extended initializer lists only available with -std=c++0x or -std=gnu++0x| w\losowanie\main.cpp|24|error: cannot convert '<brace-enclosed initializer list>' to 'int' in assignment| w\losowanie\main.cpp|25|warning: extended initializer lists only available with -std=c++0x or -std=gnu++0x| w\losowanie\main.cpp|25|error: cannot convert '<brace-enclosed initializer list>' to 'int' in assignment| ||=== Build finished: 2 errors, 2 warnings ===| , #include <iostream> #include <cstdlib> #include <ctime> using namespace std; class losowanie { int wylosowane[8]; int podane[10]; int a; int b; public: void wylosowywanie(); losowanie(); ~losowanie(); }; losowanie::losowanie() { srand(time(0)); a=0; b=0; wylosowane[8]={0,0,0,0,0,0,0,0}; podane[10]={0,0,0,0,0,0,0,0,0,0}; cout<<"Podaj 10 liczb: "; cin>>podane[0]>>podane[1]>>podane[2]>>podane[3]>>podane[4]>>podane[5]>>podane[6]>>podane[7]>>podane[8]>>podane[9]; losowanie::wylosowywanie(); }; void losowanie::wylosowywanie() { do { do { a=((rand())%11)-1; a=losowanie::podane[a]; } while (a==wylosowane[0] or a==wylosowane[1] or a==wylosowane[2] or a==wylosowane[3] or a==wylosowane[4] or a==wylosowane[5] or a==wylosowane[6] or a==wylosowane[7]); wylosowane[b]=a; b++; } while (b<10); }; losowanie::~losowanie() { cout<<"Liczby to:"<<wylosowane[0]<<", "<<wylosowane[1]<<", "<<wylosowane[2]<<", "<<wylosowane[3]<<", "<<wylosowane[4]<<", "<<wylosowane[5]<<", "<<wylosowane[6]<<", "<<wylosowane[7]<<"."<<endl; }; int main() { losowanie * obiekt=new losowanie; delete obiekt; return 0; }
PsichiX Opublikowano 11 Marca 2011 Opublikowano 11 Marca 2011 nie wywołuje sie konstruktora ot tak, musisz stworzyć obiekt, a potem go skasować: losowanie* los = new losowanie(); delete los;
kt1117 Opublikowano 11 Marca 2011 Autor Opublikowano 11 Marca 2011 To mnie w kursie okłamali, ale dalej konstruktor nie zmienia/ zmienia zbyt późno wartość wymienionych zmiennych, i dlaczego muszę jeszcze raz deklarować zmienne, które zadeklarowałem w definicji klasy? E: Teraz mam w miarę logiczny (wg. mnie) i działa: #include <iostream> #include <cstdlib> #include <ctime> using namespace std; class losowanie { int wylosowane[8]; int podane[10]; int a; int b; public: void wylosowywanie(); losowanie(); ~losowanie(); }; losowanie::losowanie() { srand(time(0)); a=0; b=0; cout<<"Podaj 10 liczb: "<<endl; cin>>podane[0]>>podane[1]>>podane[2]>>podane[3]>>podane[4]>>podane[5]>>podane[6]>>podane[7]>>podane[8]>>podane[9]; losowanie::wylosowywanie(); }; void losowanie::wylosowywanie() { do { do { a=((rand())%11)-1; a=losowanie::podane[a]; } while (a==wylosowane[0] or a==wylosowane[1] or a==wylosowane[2] or a==wylosowane[3] or a==wylosowane[4] or a==wylosowane[5] or a==wylosowane[6] or a==wylosowane[7]); wylosowane[b]=a; b++; } while (b<10); }; losowanie::~losowanie() { cout<<"Liczby to:"<<wylosowane[0]<<", "<<wylosowane[1]<<", "<<wylosowane[2]<<", "<<wylosowane[3]<<", "<<wylosowane[4]<<", "<<wylosowane[5]<<", "<<wylosowane[6]<<", "<<wylosowane[7]<<"."<<endl; }; int main() { losowanie*los=new losowanie(); delete los; return 0; } Tylko nie wiem jak wyzerować tablice, bo widocznie zapis array[n]={a,b,c,......,m} działa tylko przy deklaracji, a nie można nadać wartości zmiennej w deklaracji klasy, tzn. że muszę zerować każdą komórkę osobno?
Konrad-GM Opublikowano 11 Marca 2011 Opublikowano 11 Marca 2011 Listę inicjalizacji można użyć tylko w czasie tworzenia obiektu (deklaracja) int a[]={1,2,3}; // Dobrze int a[3]; a={1,2,3}; // Źle dla wyzerowania użyj "memset" @YXE, głupoty piszesz, nie trzeba używać 'new', aby wywołać konstruktor :)
PsichiX Opublikowano 11 Marca 2011 Opublikowano 11 Marca 2011 skoro chce, by zmienne miały zasięg obiektu, to przecież musi on istnieć. sam głupoty gadasz.
kt1117 Opublikowano 11 Marca 2011 Autor Opublikowano 11 Marca 2011 A jakie ma parametry i w jakiej bibliotece się znajduje? (memset)
Konrad-GM Opublikowano 11 Marca 2011 Opublikowano 11 Marca 2011 Wystarczy losowanie(); E: biblioteka standardowa memset(void* dest, int val, int size);
kt1117 Opublikowano 11 Marca 2011 Autor Opublikowano 11 Marca 2011 Czyli nie trzeba pisać losowanie: :( ...), nawet poza blokami funkcji zadeklarowanych w obiektach? E: Wyskakuje, że nie zadeklarowana, ale mniejsza z tym, jakoś sobie poradzę bez tego.
Konrad-GM Opublikowano 11 Marca 2011 Opublikowano 11 Marca 2011 http://www.cplusplus.com/reference/clibrary/cstring/memset/ , tutaj masz opisane działanie memset, a także wymagany header
Will Opublikowano 11 Marca 2011 Opublikowano 11 Marca 2011 Listę inicjalizacji można użyć tylko w czasie tworzenia obiektu (deklaracja) Wiesz co to jest deklaracja? ;) Czyli nie trzeba pisać losowanie: :( ...), nawet poza blokami funkcji zadeklarowanych w obiektach? W metodach danej klasy przy odwoływaniu się do funkcji, która także jest metodą(tej samej klasy) nie musisz się bawić w takie pierdoły. Do dyspozycji jest wskaźnik this, który załatwia takie sprawy. Przy samym konstruktorze inicjuj składniki klasy: class Test { Test():k(0) { } private: int k; }; Jest to znacznie szybsze. Listę inicjalizacji można użyć tylko w czasie tworzenia obiektu Można użyć tylko dla typów wbudowanych i pod'ów a nie obiektów. nie wywołuje sie konstruktora ot tak, musisz stworzyć obiekt, a potem go skasować: Przecież tworzy obiekt?
kt1117 Opublikowano 11 Marca 2011 Autor Opublikowano 11 Marca 2011 Przedtem żeby zaoszczędzić linijkę kodu dałem po prostu: losowanie::losowanie(); E:A jak mam więcej zmiennych to czym je oddzielam?
Will Opublikowano 11 Marca 2011 Opublikowano 11 Marca 2011 Przykład: WindowMgr():Singleton<WindowMgr>(),m_uWndCount(0),m_bExit(false), m_pNetworkObject(0) { }
kt1117 Opublikowano 11 Marca 2011 Autor Opublikowano 11 Marca 2011 I wtedy całe ciało konstruktora w definicji klasy, czy robić obok?
Will Opublikowano 11 Marca 2011 Opublikowano 11 Marca 2011 Jak wolisz: class T { T():k(0){} private: int k; }; lub class T { T(); private: int k; }; T::T():k(0){}
Will Opublikowano 11 Marca 2011 Opublikowano 11 Marca 2011 Znacznie lepsza, szczególnie dla złożonych typow.
kt1117 Opublikowano 13 Marca 2011 Autor Opublikowano 13 Marca 2011 Czyli będę robić osobno deklaracje i definicje, dzięki.
Will Opublikowano 13 Marca 2011 Opublikowano 13 Marca 2011 Chodziło mi o wydajność między: class T { T():k(costam){} private: int k; }; a class T { T(){k=costam;} private: int k; }; Chociaż w przypadku klas i tak rób osobno deklaracje/definicje. Klasa -> plik deklaracje Klasa.h + definicje Klasa.cpp
kt1117 Opublikowano 13 Marca 2011 Autor Opublikowano 13 Marca 2011 Aha, ostatnio mi dzielenie pliku nie wychodziło, bo wrzuciłem definicje do .cpp i cały czas wywalało błąd, że wcześniej zadeklarowano tutaj i pokazywało tą samą linijkę, w której wystąpił błąd.
Konrad-GM Opublikowano 13 Marca 2011 Opublikowano 13 Marca 2011 Tak #ifndef _HEADER_FILE_H_ #define _HEADER_FILE_H_ // Code #endif
Rekomendowane odpowiedzi
Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto
Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.
Zarejestruj nowe konto
Załóż nowe konto. To bardzo proste!
Zarejestruj sięZaloguj się
Posiadasz już konto? Zaloguj się poniżej.
Zaloguj się