Gjest Slettet-Pqy3rC Skrevet 31. oktober 2012 Del Skrevet 31. oktober 2012 Det slo meg plutselig at jeg har en vane; class MyClass { // ... diverse kode her .... friend MyClass; }; Venner med seg selv altså. Hver gang. Jeg lager aldri en klasse uten. Mye lettere mht. kopi funksjonalitet, operator overstyring etc. Så jeg satt her å spekulerte; Finnes det egentlig noen fornuftig grunn for å ikke gjøre dette (friend MyClass) ? ...eller sagt på en annen måte; Hvorfor er ikke klasser venner med seg selv i utganspunktet ? Lenke til kommentar
Valkyrex Skrevet 31. oktober 2012 Del Skrevet 31. oktober 2012 Når man setter en klasse som venn, så får den andre klassen tilgang til protected og private medlemmer av den klassen den settes som friend i. Din klasse myClass har jo allerede tilgang til alt av dette... Det skal du ikke trenge, og virker ikke logisk engang Oppsumert: du gir myClass tilgang på noe den allerede har tilgang på. En klasse er alltid sin egen "friend" for å si det sånn da. Kunne du ha posta litt kode på hvor du har måtte bruke det slik? Så kan noen her eller jeg se mer nøyaktig hvorfor du har tatt til deg denne måten å kode på? Lenke til kommentar
Gjest Slettet-Pqy3rC Skrevet 1. november 2012 Del Skrevet 1. november 2012 (endret) Oppsumert: du gir myClass tilgang på noe den allerede har tilgang på. Nja... ikke helt. Med bruk av friend blir "tilgang" utvidet; class MyClass { private: int aInternalValue; public: // ... diverse kode her .... // Operator overload; MyClass & operator = (const MyClass &c) {aInternalValue=c.aInternalValue;return *this;}; friend MyClass; }; Uttrykket aInternalValue=c.aInternalValue kompilerer nemlig ikke uten å benytte friend med seg selv. Jeg synes altså det er litt rart at det er slik og ser ikke helt nytten av å hindre klasser i å få tilgang til egne data selv om disse data er i andre objekter (av samme klasse). Kan noen gi et eksempel på når det er nyttig å ikke være friend med seg selv ? Endret 1. november 2012 av Slettet-Pqy3rC Lenke til kommentar
GeirGrusom Skrevet 1. november 2012 Del Skrevet 1. november 2012 Uttrykket aInternalValue=c.aInternalValue kompilerer nemlig ikke uten å benytte friend med seg selv. Det burde da gå helt fint... klasser har tilgang til egne private medlemmer. Lenke til kommentar
Gjest Slettet-Pqy3rC Skrevet 1. november 2012 Del Skrevet 1. november 2012 Uttrykket aInternalValue=c.aInternalValue kompilerer nemlig ikke uten å benytte friend med seg selv. Det burde da gå helt fint... klasser har tilgang til egne private medlemmer. Dette var lettere pinlig... etter en kjapp test på alle 4 kompilatorene ser det ut til at du har rett. Hmmm.... Jeg trodde dette var grunnen til at jeg startet med "friend myself" engang i tiden (nå gjør jeg det helt slavisk), så jeg har i grunn ikke testet hvordan ting fungerer uten. Det må være en grunn til at jeg begynte med dette.... (ja, ja. Da går denne dagen med til å undre seg over dette fenomenet). Lenke til kommentar
LonelyMan Skrevet 11. desember 2012 Del Skrevet 11. desember 2012 friend direktivet er bare en pisk for å unngå feil-koding, og den er utelukkende en compile-time funksjon. For å sette det i perspektiv, tenk deg en lærer i et klasserom. Læreren er din pisk, gjør du noe feil så forteller han deg det før du går ut i det virkelige livet og gjør feilen så den får virkelige konsekvenser, det er bedre å ha en pisk i klasserommet som pisker deg når du kan gjøre feil som ikke får konsekvenser, før du går ut i det virkelige livet og gjør feilen som da får alvorlige konsekvenser. Klasser og friend direktivet handler utelukkende om å redusere feil i minnekontroll samt. øke vennligheten ved minnekontroll, når programmet ditt er kompilert, så er det ingenting som heter objekter, klasser eller friends i det ferdig kompilerte programmet. Det er helt og absolutt en compile-time funksjonalitet, den har ingen betydning i det ferdig kompilerte programmet, faktisk så kan klasser bidra til å forverre programmet, men dette er prisen av å ha en tryggere koding. Lenke til kommentar
GeirGrusom Skrevet 11. desember 2012 Del Skrevet 11. desember 2012 Klasser og friend direktivet handler utelukkende om å redusere feil i minnekontroll samt. øke vennligheten ved minnekontroll, når programmet ditt er kompilert, så er det ingenting som heter objekter, klasser eller friends i det ferdig kompilerte programmet. Kommer an på kompilatoren. Dersom du bruker Visual C++ med /CLR switchen, så vil klasser være med i metadata av det ferdig kompilerte programmet, og brukes av Just-In-Time kompilatoren for lenking, arv og dokumentasjon. Lenke til kommentar
LonelyMan Skrevet 11. desember 2012 Del Skrevet 11. desember 2012 (endret) Du har rett i at objekter eksisterer i en virtuell boble utenfor kompilatoren, men alt dette bunner ned til en struktur. Hvis vi ser på hva objekter faktisk er, så er det bare en struktur, og hva er en struktur i dataverdenen, jo det er en spesiell måte å plassere biter med data. Man kan si at et objekt er tall-rekken 1-3-2... 1-3-2 er i dette tilfellet en struktur, så forteller vi kompilatoren at all data i dette objektet skal lagres i rekkefølgen 1-3-2, så har vi en struktur. Og ja, utenfor kompilatoren så er dette et objekt i en slags virtuell boble, men det bunner ned til minnekontroll. Nå vet du hvilken rekkefølge dine data er lagret og denne rekkefølgen vil aldri bli brutt så lenge du bruker klasser og objekter, rekkefølgen er garantert, og du får et robust program som nesten aldri feiler. La oss si en klasse har 3 biter med data og én enkelt metode. Så er denne klassen rett og slett en bestemt måte å definere hvordan dataene og metoden skal organiseres i minnet. Når vi vet hvordan de er organisert, så kan vi adressere metoden og dataene ved å vite adressen til objektets begynnelse i minnet. Vet du adressen til hvor objektet er, så kan du gjøre hva som helst med det, for du vet strukturen til objektet. Det er egentlig alt der er om det. Jeg kan gi et diagram over det. Her er et eksempel på et objekt og har en veldig bestemt struktur, slik som alle objekter har. Når du vet adressen hvor objektet er lagret i systemminnet, så vet du også automatisk adressen til all data i det objektet og hvor metodene er lagret, fordi objekter har struktur. Det bunner ned til minnekontroll. I gamle dager måtte vi styre minnekontroll manuelt og det førte veldig ofte til kræsj. Men med klasser så garanterer kompilatoren at du refererer riktig element i et objekt, hva som er i de objektene kan variere og hva disse igjen refererer er uvisst, men kompilatoren garanterer at du adresserer elementer i et objekt riktig. For å kalle på metoden som ligger i dette objektet, så bruker du adressen til objektet (0x410000) så plusser du på 65 bytes og kaller denne adressen. Denne kalkuleringen gjøres automatisk for deg under compile time. Om du skal endre innholdet i et data element i objektet, så vet kompilatoren den relative adressen til de individuelle elementene fordi det har en forhåndsbestemt struktur, om du sette data-element nummer 2 (som er en byte), så vil kompilatoren lage dette for deg: mov [eax+4],VERDI eax peker til objektets begynnelse, som er (0x410000).. Dette er egentlig alt klasser og objekter handler om. Lager du to unike objekter, så vil hver av disse objekter få sin egen adresse i systemminnet. Men du kan adressere alle objektene bare du vet adressen til hvor objektet begynner i systemminnet. Om byten som ligger i element nummer 2 heter f.eks "Banan" og du refererer banan i ditt objekt slik: MittObjekt->Banan := 10 så vil det konverteres til mov byte ptr [eax+4],10 Og før den gjør det, så setter kompilatoren først eax til å peke til objektets plassering i systemminnet, for å adressere riktig objekt, for der er sikkert mange objekter. Adressen til objektet avhenger av hvilket navn du benytter, har du et objekt med navn Per, så vil Per peke til sin egen unike adresse i systemminnet. Om du kaller metoden så vil det konverteres til CALL [eax+65] avhengig av om den bruker et mellomregister i tillegg, det vet jeg ikke i farten for det avhenger av hvordan kompilatoren optimaliserer tingene, og er umulig å vite på forhånd. Men det er denne relative adressen som er hele magien til objekter. I gamle dagene så var data spredt uorganisert, og du kunne aldri bruke en relativ adresse, det fantes ingen måte å håndheve struktur. Et annet eksempel, om du lager et objekt som har 2 data elementer. Du definerer første data element som en 32 bit unsigned integer. Den andre definerer du også som en 32 bit unsigned integer. Hver integer er 4 bytes lang på et 32 bit system. Nå vet kompilatoren at adressen til data element nummer 2 er +4.. Altså, den relative adressen er +4 fordi den vet at du har definert den som en 32 bit integer (som er 4 bytes lang).. Når du refererer element nummer 2 så lager kompilatoren mov [eax+4],VERDI for den vet at element som ligger i begynnelsen er 4 bytes lang. Om du bestemmer deg for å endre første data element fra en 32 bit unsigned integer til en enkelt byte, så endrer også kompilatoren den relative adressen til neste element, som da blir mov [eax+1],VERDI, fordi du nå har en byte som ligger først i objektet. Det er denne relative adresseringen som gjør klasser så brukervennlig, strukturen forteller kompilatoren hvordan den skal adressere dataene, og den er garantert. Metoden som ligger i objektet inneholder en peker til den faktiske koden som metoden inneholder, for å slippe å duplisere metoden i alle objekter, så den leser bare en peker fra metoden, så hver metode i et objekt er 4 bytes lang, for den inneholder bare en peker. Den laster pekeren ved å hente adressen først mov edx,[eax+64] og så CALL [edx] Endret 11. desember 2012 av LonelyMan Lenke til kommentar
GeirGrusom Skrevet 11. desember 2012 Del Skrevet 11. desember 2012 (endret) Dette er kun for det mest trivielle tilfellet på en x86-32 prosessor dog. Visual C++ med /CLR kompilerer ikke til x86, men til .NET CLR. Endret 11. desember 2012 av GeirGrusom Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå