odwoływanie sie do obiektow tablicy 2 wymiarowej

0

Mam taki problem. Stworzylem tablice 2 wymiarowa, ktora tworzy plansze zlozona z obiektow, tworzonych konstruktorem domniemanym.Teraz chcialbym sie odwolac do konkretnych obiektorw mojej tablicy np :
tablica [5][5] celem podmiany istniejacych na nowe. Staram sie wykombinowac jak to zrobic. Mysle nad dwoma metodami. Albo funkcja aktualizacyjna, albo podmiana konstruktora domniemanego na zywkly.

Głowny problem polega na tym, iz nie wiem jak w tablicy wielowymiarowej moge odwolac sie do konretnej pozycji celem zmiany wartosci sedziacego tam obiektu. Powiem tylko ze jesli w petlach for zmienie obiekt () na obiekt(1), wszystkie elementy zmieniaja sie z "." na "x", zgodnie z dzialaniem konstruktorow. Nie wiem jak zmieic tylko jeden z nich :/

Ponizej przedstawiam kod :

#include <iostream>
#include <string.h>
using namespace std;

//klasy/////////////////////////////

class obiekt
{
	int mnozenie;
	char nazwa[15];
public:
	int poz_x,poz_y;
	int liczba;
	int ilosc;
	


	obiekt ( int a);
	obiekt ();
	void aktualizuj()         /*jedna wersja rozwiazania, poprzez funkcje*/
	{
		
		strcpy(nazwa,"x");
		cout << nazwa;
		mnozenie=1;
	}
	
};

obiekt::obiekt(int a):mnozenie(a)   /*druga wersja rozwiazania poprzez konstruktor*/
{
	strcpy (nazwa ,"x");
	cout << nazwa;
	mnozenie=1;
}

obiekt::obiekt()
{
	strcpy (nazwa ,".");
	cout << nazwa;
	mnozenie=0;
}

int main()
{
	obiekt tablica [20][20];
	cout << endl;
	cout << "\n_____________";
	cout << "\n Plansza : \n";
	for (int i=0;i<20;i++)
	{
		for (int j=0;j<20;j++)
		{
			tablica[i][j]=obiekt();
		}
		cout << "\n";
	}
	cout << "____________";
	cout << "\n\nLiczba obiektow      :";
	cout << "\nLiczba wykonan petli :";
	cout << "\n\n\n\n";
	
	tablica[5][5].aktualizuj();      /*nie mam pojecia jak sie odwolac do tego obiektu :/*/
}

O i jeszcze jedno, po skompilowaniu pojawiaja mi sie jakby 2 te same wersje tablicy, z tym ze jedna jest ciagiem obiektow nie poukladanych tak jak w tej drugiej. Wydaje mi sie ze te tablice pokazuja te same obiekty i zmiany pojawiajace sie na jednej beda takie same jak na drugiej. Jednym slowem sa identyczne ?

0

Co chcesz zrobić? Kod wygląda poprawnie, więc nie rozumiem o co ci chodzi.
Zauważyłem tylko głupotę w konstruktorze:

obiekt::obiekt(int a) :
        mnozenie(a)   // tu ustawiasz zmienną na wartość a
{
        strcpy (nazwa ,"x");
        cout << nazwa;
        mnozenie=1; // a następnie tu zmieniasz wartość tej zmiennej zawsze na 1
}

Nie wiedząc jaki chcesz osiągnąć efekt nie jestem w stanie zrozumieć z czym masz problem. (w ostatniej linijce dostajesz się do tego obiektu)

0

[poprawiam, żeby nie wprowadzać niepotrzebnego zamieszania - oryginalny post zawierał informacje nie z C++]
Powinieneś użyć konstrukcji:

obiekt* tablica[20][20];
...
tablica[i][j] = new obiekt();

Wtedy możesz w pełni kontrolować elementy tablicy. Używanie bezpośrednio tablicy obiektów jest mocno mylące. Wtedy składnia dostępu może wyglądać tak: tablica[i][j]->aktualizuj();

Teraz druga sprawa. Wszelkie korzyści jakie uzyskujesz z posługiwania się składnią obiektową są przez Ciebie kompletnie niwelowane przez użycie tablicy z C - tym bardziej tablicy tablic - która jest protezą nieistniejącej w C/C++ tablicy wielowymiarowej. Przede wszystkim zwykłe tablice nie posiadają żadnego sprawdzania zakresu.
Do przechowywania dużej ilości obiektów powinieneś użyć obiektu np. vector ze standardowej biblioteki C++. Nie dość, że ma jakieś zabezpieczenia (tablice z C - żadnych), to jeszcze składnia nie jest myląca.

I jeszcze coś do wyjaśnienia.
Jedyny sposób na stworzenie obiektu (automatycznego/lokalnego) na stosie, to użycie konstrukcji:
obiekt zmienna = obiekt();
lub
obiekt zmienna();
lub
obiekt* wskaznik = &obiekt();

Jeżeli obiektów ma być wiele i mają być umieszczone w jakimś agregacie, to najlepiej jest tworzyć obiekty na stercie za pomocą operatora new. Trzeba tylko pamiętać, żeby przed końcem bloku, gdzie tablica zostanie zlikwidowana zlikwidować wszystkie istniejące obiekty w tablicy.

I jeszcze co do pytania o to czy lepiej jest zmieniać wartość obiektu w tablicy czy też usuwać go i w tym samym miejscu przypisywać nowy - to obie metody działają. Jeżeli obiekty są duże i skomplikowane, to czasem warto je aktualizować, a jeżeli małe i proste, to wymieniać. Wadą pierwszego rozwiązania jest komplikacja samego obiektu, a wadą drugiego potencjalna fragmentacja sterty. Jednak na podczas nauki obie wady nie mają większego znaczenia.

0
Olamagato napisał(a)

Po pierwsze w kodzie jest bardzo poważny błąd. Używasz takiej konstrukcji:

for (int j=0;j<20;j++)
{
tablica[i][j]=obiekt();
}

> W każdym przebiegu pętli tworzysz na stosie automatyczną zmienną obiektową obiekt, inicjujesz ją konstruktorem domyślnym, po czym przypisujesz ją do j-tej komórki w i-tej tablicy zmiennej tablica. Zaraz po tym kończy się blok pętli co powoduje wywołanie domyślnego destruktora dla przypisanego tam obiektu, co powoduje, że jest on natychmiast niszczony (jeszcze przed kolejną iteracją). To co zostaje w każdej komórce, to "zwłoki" nieistniejącego już obiektu. Wywoływanie na jego rzecz metod, to ożywianie trupa.
> Gdyby obiekt posiadał destruktor zerujący wszystkie jego pola (dobra praktyka), to przekonałbyś się, że w tablicy posiadasz "obiekty" składające się z samych zer.

Sorry, ale o czym Ty pierdolisz? Tam jest tablica obiektów, leci automatycznie wygenerowany operator przypisania KOPIUJĄCY wszystkie pola obiektu tymczasowego, nic się nie zeruje! Obiekt jest niszczony dopiero PO użyciu! Destruktor nic nie zmiania!


 > ##### Olamagato napisał(a)
> Powinieneś tutaj użyć konstrukcji:
> <code>
obiekt& tablica[20][20];
...
tablica[i][j] = *new obiekt();

Takie wyrażenie stworzy tablicę referencji na stosie i dowiązanie do każdego obiektu utworzonego na stercie poprzez tablicę.

Idiotyzm jakich mało, referencję inicjalizuje się raz, w momencie utworzenia, przecież to się nawet nie skompiluje! Tablica referencji jest tworem, który w C++ jest zakazany! Kolejna sprawa to memleak, jaki tworzysz - pamięć zajmowana przez te obiekty nie zostanie zwolniona.

Ewentualnie inaczej:

obiekt* tablica[20][20];
...
tablica[i][j] = new obiekt();


Już bardziej poprawne...



> Teraz druga sprawa. Wszelkie korzyści jakie uzyskujesz z posługiwania się składnią obiektową są przez Ciebie kompletnie niwelowane przez użycie tablicy z C - tym bardziej tablicy tablic - która jest protezą nieistniejącej w C/C++ tablicy wielowymiarowej. Przede wszystkim zwykłe tablice nie posiadają żadnego sprawdzania zakresu.

Może się mylę, ale tablice mają się nijak do programowania obiektowego. Tablice nie są 'z C', to integralny element C++. W C++ nie ma tablic wielowymiarowych? Cóż, człowiek uczy się całe życie...


> Do przechowywania dużej ilości obiektów powinieneś użyć obiektu tablicy dynamicznej ze standardowej biblioteki C++. Nie dość, że ma zabezpieczenia, to jeszcze składnia nie jest myląca.

Nie istnieje KLASA tablicy dynamicznej w bibliotece standardowej, taką dodaje dopiero Boost. Standardowy operator[] z vectora niczego nie zabezpiecza... Co najwyżej 'myląca' składnia z użyciem metody at(). Gdzie widzisz mylącą składnię?


> I jeszcze coś do wyjaśnienia.
> Jedyny sposób na stworzenie obiektu (automatycznego/lokalnego) na stosie, to użycie konstrukcji:
> obiekt zmienna = obiekt();
> lub 
> obiekt zmienna();
> lub
> obiekt* wskaznik = &obiekt();

Jeszcze coś do wyjaśnienia: C++ to nie C#, chłopcze. Drugie wyrażenie ma prawo się nawet nie skompilować, trzecie to idiotyzm, pierwsze tworzy niepotrzebnie obiekt tymczasowy dla konstruktora kopiującego. Prawidłowo pisze się po prostu:

`Typ obiekt;`
Ten kod wywołuje konstruktor domyślny.


> Oznacza to, że aby wpakować np. 20 lokalnych obiektów do tablicy bez ich niszczenia, trzeba by zrobić taką konstrukcję:
> obiekt tablica[5] = { obiekt(), obiekt(), obiekt(), obiekt(), obiekt() };
> lub
> obiekt* tablica[5] = { &obiekt(), &obiekt(), &obiekt(), &obiekt(), &obiekt() };
> Lecz kompilator może zaprotestować zależnie od opcji kompilacji.

Opcje kompilacji <b>[CIACH]</b> nie mają nic do gadania. Agregacja ma się nijak do zagadnienia - sama definicja tablicy nie-dynamicznej jest wywołaniem konstruktora domyślnego na każdym jego elemencie. Pierwsza forma jest równoważna z zapisem 'obiekt tablica[5];', druga to idiotyzm, za który powinno się jaja przy samym gardle wyrywać.

Takie pytanie - kiedy ostatni raz pisałeś w C++ i dlaczego Twoim ostatnim programem było hello-world? Nie umiesz - nie rób krzywdy innym swoimi urojeniami.
0
sadfg napisał(a)

Sorry, ale o czym Ty [CIACH!]? Tam jest tablica obiektów, leci automatycznie wygenerowany operator przypisania KOPIUJĄCY wszystkie pola obiektu tymczasowego, nic się nie zeruje!

Racja. Niszczony jest obiekt pierwotny i racja, że konstruktor kopiujący stworzy obiekt tymczasowy w elemencie tablicy. Zapomniałem o tym ponieważ rzeczywiście na codzień piszę już w trochę lepszym języku niż zdziadziały C++.
Ale sposób Twojej wypowiedzi jest fatalny.

Obiekt jest niszczony dopiero PO użyciu!

A możesz mi "mędrcu" wyjaśnić jak kompilator ma się dowiedzieć kiedy to jest "po użyciu"? Bo jedyne co kompilator wie, to kiedy kończy się blok powodujący likwidację zmiennych automatycznych utworzonych w tym bloku.

przecież to się nawet nie skompiluje! Tablica referencji jest tworem, który w C++ jest zakazany!
Kolejna sprawa to memleak, jaki tworzysz - pamięć zajmowana przez te obiekty nie zostanie zwolniona.

Ano tak. Miałem napisać tylko o wskaźnikach, ale dopisałem referencje z rozpędu. Referencje z C++ są rzeczywiście biedne i rzeczywiście zaimportowałem sobie je nie z tego języka.

Może się mylę, ale tablice mają się nijak do programowania obiektowego. Tablice nie są 'z C', to integralny element C++.

Tablice są z C. A jak nie wierzysz, to sobie poczytaj Stroustrupa, który wyraźnie sam to powiedział. A jakoś nie słyszałem o innym twórcy C++.

W C++ nie ma tablic wielowymiarowych? Cóż, człowiek uczy się całe życie...

Nie ma. Jakbyś nie kombinował w C, ani C++ nie ma tablic wielowymiarowych. Istnieje tylko proteza tych tablic w postaci tablic przechowujących tablice itd. A, że ludzie nazywają to tablicami wielowymiarowymi, to ich problem.

Nie istnieje KLASA tablicy dynamicznej w bibliotece standardowej, taką dodaje dopiero Boost. Standardowy operator[] z vectora niczego nie zabezpiecza...

Tak, miałem na myśli vectora, którego można traktować jak tablicę dynamiczną.
A co do mylenia, to miałem na myśli oczywiście składnię używania zwykłych tablic w C/C++. Jeżeli nie uważasz, że jest ona myląca, to skąd te miliony zapytać o problemy z tablicami w C i C+? Nawet na tym forum użycie i składnia tablic zajmuje całkiem pokaźną ilość tematów.

I jeszcze coś do wyjaśnienia.
Jedyny sposób na stworzenie obiektu (automatycznego/lokalnego) na stosie, to użycie konstrukcji:
obiekt zmienna = obiekt();
lub
obiekt zmienna();
lub
obiekt* wskaznik = &obiekt();

[CIACH!] //quetz: jest roznica miedzy kiepska wypowiedzia a czysta pyskowsa, i nie jest wazne ile masz lat Ty ani Twoj rozmowca

Typ obiekt;
Ten kod wywołuje konstruktor domyślny.

Obie składnie są równoważne. Typ obiekt(); jest o tyle wartościowszy , że informuje o wywołaniu konstruktora w przeciwieństwie składni bez nawiasów.

0

A możesz mi "mędrcu" wyjaśnić jak kompilator ma się dowiedzieć kiedy to jest "po użyciu"?

Standard jeżyka jasno definiuje czas życia zmiennych lokalnych, obiektów tymczasowych itd. - w tym nie ma magii, której mógłbyś nie rozumieć.

Gdzie są te opcje kompilatora, o których pisałeś? Nie udowodniłeś swoim postem absolutnie nic - ani jednego argumentu nie obaliłeś, nie potwierdziłeś też swoich.

Czym różni się ciągła tablica tablic od tablicy wielowymiarowej? Pytam bo standard języka nazywa to tablicą wielowymiarową, ale autorzy pewnie się nie znają, nie to co Ty... [CIACH!] //quetzal: obelgą są nie tylko słowa wulgarne..

Niszczony jest obiekt pierwotny i racja, że konstruktor kopiujący stworzy obiekt tymczasowy w elemencie tablicy.

A ten idiotyzm przeoczyłem... gdzie w elemencie tablicy masz obiekt tymczasowy?!

0

Bardzo dziekuje ze pomoc. Teraz pozostaje tylko dobrze przysiasc i kombinowac dalej :).
Juz wyjasniam sens calego programu. Ma on na celu symulowac rozmnazanie sie obiektow.

System jest nastepujacy:

-stworzenie planszy na ktorej obiekty maja sie mnozyc

-inicjalizacja 2 pierwszych obiektow

-mnozenie ich polegajace na sprawdzeniu istniejacych obiektow (jesli sa obok siebie i wczesniej sie nie mnozyly, program sprawdza ile jest wolnych miejsc dookola "rodzicow", nastepnie losuje ilosc "dzieci" i wstawia je w te pola. Oczywisice ilosc dzieci nie moze przekroczyc ilosci wolnych miejsc).

(planuje jeszcze stowrzenie mozliwosci "smierci" istniejacych juz obiektow po uplywie jakiegos czasu)

0

Czym różni się ciągła tablica tablic od tablicy wielowymiarowej? Pytam bo standard języka nazywa to tablicą wielowymiarową

Choćby tym, że tablica tablic nie jest w stanie uzyskać właściwości tablicy nierównej. Jeżeli nie słyszałeś o tym, to polecam douczyć się pojęcia "ragged array". Formalnie tablica tablic jest tablicą wielowymiarową - jednak najprymitywniejszą i chyba najgorszą z możliwych implementacji.

Autora tematu przepraszam, za ewentualne wprowadzenie w błąd pierwszą wersją posta.
Nie jestem nieomylny, a czas swoje robi.

0

Choćby tym, że tablica tablic nie jest w stanie uzyskać właściwości tablicy nierównej. Jeżeli nie słyszałeś o tym, to polecam douczyć się pojęcia "ragged array".

Znam jagged array'e... Poza tym tablica wielowymiarowa != jagged, jagged to tylko jeden bardzo specyficzny rodzaj tablicy wielowymiarowej.

Mam tylko jedną prośbę - nie wiesz czegoś, nie jesteś pewny to nie pisz. Gdybyś nie pisał tego co Ci się 'wydaje' to by problemu nie było. Z mojej strony również EOT, po prostu mam uczulenie na ludzi piszących bzdury bez zastanowienia.

0
Olamagato napisał(a)

Typ obiekt;
Ten kod wywołuje konstruktor domyślny.

Obie składnie są równoważne. Typ obiekt(); jest o tyle wartościowszy , że informuje o wywołaniu konstruktora w przeciwieństwie składni bez nawiasów.

nie prawda:

Typ obiekt();

jest zawsze traktowana jako forward declaration funkcji "obiekt" o sygnaturze Typ(void) [*prosze nie zaczynac dyskusji o () vs. (void)]
i nigdy nie powinno byc traktowane jako deklaracja zmiennej, nawet jesli wstawisz do nawiasow jakies parametry.

prawidlowa skladnia takiej inicjalizacji to:

Typ obiekt;
Typ obiekt = Typ();
Typ obiekt = Typ(1,2,3,4);

w zadnym z powyzszych przypadkow NIE jest wywolywany konstruktor kopiujacy, poniewaz jest to inicjalizacja a nie przypisanie!

Olamagato napisał(a)

Słuchaj źle wychowany człowieku - jeżeli piszę posta, to z intencją pomocy komuś innemu (..)

Jak zareagujesz, jesli ktos bedzie Ci wmawial ze 30*30 = 250, a potem wykrecal ze mu sie pomieszalo, gdyz zwykle operuje w systemie 12-stkowym? Nie mozna odmowic Ci, ze probujesz pomoc, ale nie siej jeszcze wiekszego zametu w momencie gdy ktos Ci w ten, albo inny sposob zwroci uwage ze sie pomyliles. Jesli nie podoba Ci sie forma, napisz mu na priva, olej, albo zglos wypowiedz do moderacji. Po to na dole pod kazdym postem jest taki maly przycisk "raport".

Olamagato napisał(a)

Czym różni się ciągła tablica tablic od tablicy wielowymiarowej? Pytam bo standard języka nazywa to tablicą wielowymiarową

Choćby tym, że tablica tablic nie jest w stanie uzyskać właściwości tablicy nierównej. Jeżeli nie słyszałeś o tym, to polecam douczyć się pojęcia "ragged array". Formalnie tablica tablic jest tablicą wielowymiarową - jednak najprymitywniejszą i chyba najgorszą z możliwych implementacji.

jesli by byla najgorsza, nie byla by tak powszechnie uzywana, nie czarujmy sie, ludzie nie sa masochistami.</quote>
tablice o zmiennej dlugosci wiersza sa dosc wygodne - ale szczerze mowiac, nie rozumiem do czego próbujesz sie przyczepic, poniewaz w C mozesz takowa uzyskac umiejetnie operujac wskaznikami, a w C++'ie mozesz sobie takowa bardzo szybko stworzyc: vector<vector<x> > albo skorzystac z gotowych klas boosta/etc btw. boost jest de facto standardem, nie uzywanie go to tak jakbys sie zapieral przed uzywaniem ze STL albo System::Generic.
to, ze w jezyku/platformie X musisz uzyc trzynastu znakow na to co w jezyku/platformie Y uzyskasz piecioma, nie znaczy ze X/Y jest lepsze/gorsze/zacofane/superwypas.. zeby bylo smieszniej, jak sie blizej przyjrzec ragged/jagged [synonimy] to sie okazuje ze na dnie sa konstruowane zazwyczaj tak jak w C, nawet nie C++, poniewaz ten stary "najgorszy" sposob jest typowych przypadkach uzycia najwydajniejszy

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