Eli jos mulla on luotu olio ja haluan jonkun funktion käyttävän viittausta siitä
niin kuinka esittelen funtion parametrin oliosta ja kuinka otan sen funktion kuvauksessa vastaan?
Funktion prototyyppi voisi näyttää tällaiselta:
void kasittele_oliota(omaluokka& olio);
Määrittelyssä sitten kirjoitat vain tuon funktion sisällön. Oliota (viittausta varsinaiseen olioon) käytetään ihan normaalisti funktion sisällä.
Tässä luokka.
class Maila { private: short x,y,leveys,hitted,Liima,hittype,fx,fy,fdir; short fhitted; char Magnet,Heavy,Fire,Laser,Aim,Missile,notnow,Triple,Grenade,Twin,Vittuilu,Kaveri; bool LittleBall; short Multi; public: short GetX(void) {return x;} short GetY(void) {return y;} void SetX(short a) {x=a;} short GetFX(void) {return fx;} short GetFY(void) {return fy;} void SetFX(short a) {fx=a;} short GetLeveys(void) {return leveys;} void SetLeveys(short a) {leveys=a;} void SetY(short a) {y=a;} void SetFY(short a) {fy=a;} short GetHit(void) {return hitted;} short GetFriendHit(void) {return fhitted;} short GetHitType(void) {return hittype;} void SetHit(short a,short b) {hitted=a;hittype=b;} void SetFriendHit(short a,short b) {fhitted=a;} void DecHit(void) {hitted--;} void DecFriendHit(void) {fhitted--;} void IncMissile(void) {Missile++;} void DecMissile(void) {if (Missile>0) Missile--;} short GetMissile(void) {return Missile;} void SetMissile(short a) {Missile=a;} char GetMagnet(void) {return Magnet;} void SetMagnet(char a) {Magnet=a;} char GetHeavy(void) {return Heavy;} void SetHeavy(char a) {Heavy=a;} void SetFire(char a) {Fire=a;} char GetFire(void) {return Fire;} void SetTwin(char a) {Twin=a;} char GetTwin(void) {return Twin;} void SetMulti(short a) {Multi=a;} short GetMulti(void) {return Multi;} void SetLaser(char a) {Laser=a;} char GetLaser(void) {return Laser;} char GetAim(void) {return Aim;} void SetAim(char a) {Aim=a;} char GetNotnow(void) {return notnow;} void SetNotnow(char a) {notnow=a;} void SetTriple(char a) {Triple=a;} char GetTriple(void) {return Triple;} void SetGrenade(short a) {Grenade=a;} short GetGrenade(void) {return Grenade;} void SetLiima(short a) {Liima=a;} short GetLiima(void) {return Liima;} void DecLiima(void) {if (Liima>0) Liima--;} short GetFriend(void) {return Kaveri;} void SetFriend(short a) {Kaveri=a;} short GetFriendDir(void) {return fdir;} void SetFriendDir(short a) {fdir=a;} void IncX(short a); void IncY(short a); void IncFX(short a); void SetLittleBall(bool a) {LittleBall=a;} bool GetLittleBall(void) {return LittleBall;} }; void Maila::IncX(short a) { x+=a; if (x<224) x=224; if ((Twin==0 || Twin==2) && x>768-leveys) x=768-leveys; if (Twin==1 && x>768-(64+32+64)) x=768-(64+32+64); } void Maila::IncFX(short a) { fx+=a; if (fx<224) {fx=224;fdir=1;} if (Twin==0 && fx>768-leveys) {fx=768-leveys;fdir=0;} if (Twin==1 && fx>768-(64+32+64)) {fx=768-(64+32+64);fdir=0;} } void Maila::IncY(short a) { y+=a; if (y>611) y=611; }
Tässä dynaaminen varaus ja M:n käyttö ekan kerran.
Jostain syystä ei huoli parametriksi &M tai M.
Game=AlkuParkki; Maila *M=new Maila; AlkuParkki(true,*M); delete M;
Näin otan vastaan M:n ja käytän sitä.
char AlkuParkki(bool opt,Maila &M) { Ohjaus(false,M); }
Tässä prototyypit
char AlkuParkki(bool opt,Maila &M); bool Ohjaus(bool kierros,Maila &M);
Ohjelma toimii moitteetta siellä missä mailan arvoja käytetäänkin eli itse pelissä ei ole ongelmaa mutta olenko tehnyt kaiken oikein?
Käytät viittauksia, mutta Maila on osoitin. Nuo kai pitäis muuttaa:
Maila M;
AlkuParkki(true, M);
edit: Katoin oppaita uudemman kerran ;)
DumTom kirjoitti:
Jostain syystä ei huoli parametriksi &M tai M.
Maila *M=new Maila; AlkuParkki(true,*M);
&M on tyyppiä Maila** ja M on tyyppiä Maila*. Kumpikaan näistä ei kelpaa kun tarvitaan Maila&.
*M on oikea tapa. Vaihtoehtoisesti voit välttää pointtereita.
Maila M; AlkuParkki(true,M);
Suosittelen lämpimästi, että jatkossa sisennät koodisi (tai vaihtoehtoisesti käytät IDE:ä, joka sisentää automaattisesti). Tuota on todella vaikea lukea.
Ilmeisesti siis toimin oikein?
Tässä kiperämpi kysymys.
Tässä luokka:
class Ball { private: float x,y; short suunta,locked,fxero,xero,stopped,locktype,triotime,trio_on; float ex,ey; // ennen törmäystä float spd; char on,SNDIV,Hitted; char size; bool friendmagnet; public: float GetX(void) {return x;} float GetY(void) {return y;} void SetX(float a) {x=a;} void SetY(float a) {y=a;} void DecX(short a) {x-=a;} void IncX(short a) {x+=a;} float GetEX(void) {return ex;} float GetEY(void) {return ey;} void SetEX(float a) {ex=a;} void SetEY(float a) {ey=a;} short GetSuunta(void) {return suunta;} void SetSuunta(short a) {suunta=a;} void SetNoDivide(char a) {SNDIV=a;} char GetNoDivide(void) {return SNDIV;} short GetLocked(void) {return locked;} void SetLocked(short a) {locked=a;} void DecLocked(void) {if (locked>0) locked--;if (locked==0) locktype=0;} char GetOn(void) {return on;} void SetOn(char a) {on=a;} short GetXero(void) {return xero;} void SetXero(short a) {xero=a;} void SetStop(short a) {stopped=a;} short GetStop(void) {return stopped;} void SetHitted(char a) {Hitted=a;} char GetHitted(void) {return Hitted;} void SetLockType(short a) {locktype=a;} short GetLockType(void) {return locktype;} void SetTrioTime(short a) {triotime=a;} short GetTrioTime(void) {return triotime;} void SetTrio(short a) {trio_on=a;} short GetTrio(void) {return trio_on;} void IncTrioTime(void) {triotime+=1;} short GetFXero(void) {return fxero;} bool GetFRIENDKYYTI(void) {return friendmagnet;} void SetFRIENDKYYTI(bool a) {friendmagnet=a;} void SetFXero(short a) {fxero=a;} char GetSize(void) {return size;} void SetSize(char a) {size=a;} // 0=little 1=normal 2=big };
Tässä dynaaminen varaus:
Ball *B=new Ball[50];
Kuinka käsittelen B:tä? Eli miten toimin jotta voin käyttää mitä olion alkiota vain?
Eli prototyyppi ja vastaanottavasta fukntiosta esimerkki.
Kiitos etukäteen!:)
Kaikkiin näihin kysymyksiin löytyy vastaus oppaasta.
Onko tämä oikein tehty?
Peli kaatuu nyt kun sen aloittaa new gamesta.
Debugilla sain toimimaan mutta vain yksi pallo liikkui ja kone kaatui quitin jälkeen aivan täydellisesti.
Maila *M=new Maila; Player *PL=new Player; Missile *MIS=new Missile[10]; Maila *M=new Maila; Player *PL=new Player; Missile *MIS=new Missile[10]; Ball *B=new Ball[50]; AlkuParkki(true,*M,*PL,MIS,B); delete [] B; delete [] MIS; delete PL; delete M; Reset();exit(0); return 0; } char AlkuParkki(bool opt,Maila &M,Player &PL,Missile *MIS,Ball *B) {
Eikö niitä pelin muuttujia voi käsitellä ihan lokaaleina muuttujina? Tällöin ei olisi lainkaan (tällaisia) ongelmia.
Tää peli on alunperin tehty globaaleilla olioilla ja alkoi jossain vaiheessa temppuilla kaatumisella lopettettaessa.
Koodi on vuoden vanhaa.
Viittaamaan joutuu väkisin ja haluaisin oppia tuon dynaamisen taulukon viittauksen.
Seuraavaa projektia aloitellessa on sitten viisaampi ja osaan suunnitella paremmin.
Tässä sätöksessä joka on hieno mutta viallinen siten että joudun viittaamaan koko ajan funktiosta toiseen kaikki oliot. Tosin kaikki funktiot eivät tietenkään tarvitse kaikkia tietorakenteita. Luulin kun tuo Missilen jälkeen toimi ohjukset ihan hyvin että nytpä voin sitten naputella tuon Ballin samalla tavalla mutta kun tota ajattelen nyt niin enhän siinä viittaa mitään vaan käytän osoittimia....
AUTTAKEE!
Ei pidä ikinä rakastua koodiinsa niin paljoa, ettei kykene sitä poistamaan. Tuosta ei tule toimivaa peliä ikinä, joten siltä osin voit aloittaa puhtaalta pöydältä. Lataa esimerkiksi matopelioppaan osa 3, josta poistat kaiken peliin liittyvän koodin. Nyt sinulla on toimivan pelin runko, johon alat koodaamaan omaa peliäsi.
Toimiva peli sinulla pitäisi olla suunnilleen parin päivän koodaamisen jälkeen.
No toi nyt on täyttä paskaa. Oon tehny useita pelejä aikasemmin.
Suurimman osan dossin suojatussa tilassa tosin.
Tosta tulee toimiva peli heti kun viitaukset on kunnossa ja periksi en anna.
DumTom kirjoitti:
No toi nyt on täyttä paskaa. Oon tehny useita pelejä aikasemmin.
Niin minäkin olen tehnyt pelejä ihan samalla tavalla, kuin tämä sinunkin pelisi. Minäkin luulin, että teen ihan hyviä pelejä. Kokemuksen myötä olen tosin oppinut katsomaan omaa koodia hiukan kriittisemmin.
DumTom kirjoitti:
Tosta tulee toimiva peli heti kun viitaukset on kunnossa ja periksi en anna.
Periksiantamattomuus on toki ohjelmoidessa hyve, mutta sokea oman koodin tuijottelu ei tee hyvää usko pois.
Ainoa asia mikä mun tarttee tietää on taulukko-olion viittaus.
Noi tavan oliot toimii viittaamalla hienosti.
Mutta olioita on vielä 6 kappaletta joista 4 muistaakseni taulukoita.
Toki tiedän että noi pätkät mitkä oon tohon laittanu saa pelin näyttämään aloittelijan tekemältä.
Olen tarkistanut kaikki surfacejen ja äänien vapautukset,ei vikaa.
Dossilla koodatessa olisi globaalit oliot kelvanneet.
Eli jos katson kirjasta tavallisen taulukon viittauksen niin voiko sen soveltaa taulukko-olioon?
Jos pointterien käyttö on liian vaikeaa, älä käytä niitä.
std::vector on hyvä dynaaminen taulukko ja näytin jo aiemmassa viestissäni, miten voit välttää tavallisia pointtereita.
Neuvomista helpottaisi jos näkisi enemmän relevanttia koodia (ja vähemmän järjetöntä tauhkaa).
Mahtuisko koko koodi tuonne? http://pastebin.com/ :)
Poistin koodista kaiken Balliin liittyvän.
Onko se nyt hyvät ihmiset liikaa pyydetty että näyttäisitte kuinka osoittimia/viittauksia käytetään oliotaulukossa?
On se melko paljon vaadittu, jos et kerro miten niitä tulee käyttää. Vähän arvailun varaan jää sekin, haluatko taulukkoosi olioita vai osoittimia.
Kirjoitin äkkiä yhden tavan, joka ei kuitenkaan kuvaa tapaa miten normaalisti ohjelmoisin C++:lla. Mielestäni tämä tässä käyttämäni array new (new[]-operaattori) kuuluu lähes aina luokan sisään, joka hallitsee sen käyttöä ja vastaavaa delete[]-operaattoria. Mutta menköön, kerrot sitten ehkä miksi tämä ei yhtään vastaa sitä asiaa mitä meiltä odotit... ja homma etenee... hiljalleen...
#include <iostream> class Noisy_Base { public: virtual void make_noise() = 0; virtual ~Noisy_Base() {} }; class Buzzer : public Noisy_Base { virtual void make_noise() { std::cout << "BZZZZ!!" << std::endl; } }; class Beeper : public Noisy_Base { virtual void make_noise() { std::cout << "Bleeep!!!" << std::endl; } }; class Whiner : public Noisy_Base { virtual void make_noise() { std::cout << "Waah waah!!" << std::endl; } }; const size_t howmany = 10; int main() { Noisy_Base **noises = new Noisy_Base*[howmany]; // fill the array for (size_t i=0; i<howmany; i++) { switch (i%3) { case 0: noises[i] = new Buzzer; break; case 1: noises[i] = new Beeper; break; case 2: noises[i] = new Whiner; break; default: throw "wtf!"; } }; // iterate over it for (size_t i=0; i<howmany; i++) { noises[i]->make_noise(); } // delete objects via pointers for (size_t i=0; i<howmany; i++) { delete noises[i]; } // delete the array delete[] noises; return 0; }
Sen pitäisi kääntyä ilman varoituksia ja tulostaa seuraavaa. Tosin join vasta yhden kupin teetä ja on aikainen, joten en tiedä mitä se oikeasti tekee ihan varmasti :)
BZZZZ!! Bleeep!!! Waah waah!! BZZZZ!! Bleeep!!! Waah waah!! BZZZZ!! Bleeep!!! Waah waah!! BZZZZ!!
Muoks: Kuitenkin unohtui käyttää delete[]-operaattoria, vaikka ajattelinkin, että piti. Korjasin vihreen.
DumTom kirjoitti:
Onko se nyt hyvät ihmiset liikaa pyydetty että näyttäisitte kuinka osoittimia/viittauksia käytetään oliotaulukossa?
On. XY-ongelma. http://meta.stackoverflow.com/a/66378
En viitsi ruveta arvailemaan mitä tuolla kysymyksellä oikeasti haet ja ehdottaa vastauksia kaikkiin eri vaihtoehtoihin joita keksin.
Kun et selvästikään hallitse C++:aa kovin hyvin, kannattaisi kysyä korkeamman tason kysymyksiä. Esimerkiksi "Haluan antaa funktiolle parametrina N kappaletta Foo-olioita, miten tämä kannattaa tehdä?"
Testasin peliä siten että palikoista tippui vain ohjusrullia ja ammuskelin niitä useita kerralla ja ei mitään ongelmaa.
Eli ongelmani on ratkennut.
Tein jonkun huolimattomuusvirheen ton Ball taulukon kanssa.
Teen sen tänään huolellisemmin uudelleen.
Kiitos kaikille kuitenkin. Osaan olla rasittava ja laiska!:)
Aihe on jo aika vanha, joten et voi enää vastata siihen.