Warning: preg_replace(): The /e modifier is no longer supported, use preg_replace_callback instead in /www/webvol34/an/96qmbdpibm1sspm/danielliljeberg.se/public_html/blog/wp-content/mu-plugins/gkphp.php on line 1
C « Categories « Daniel Liljeberg

Arkiv för ‘C’ kategori

Warning: Use of undefined constant archives - assumed 'archives' (this will throw an Error in a future version of PHP) in /www/webvol34/an/96qmbdpibm1sspm/danielliljeberg.se/public_html/blog/wp-content/themes/cordobo-green-park-2/archive.php on line 32

Warning: Use of undefined constant page - assumed 'page' (this will throw an Error in a future version of PHP) in /www/webvol34/an/96qmbdpibm1sspm/danielliljeberg.se/public_html/blog/wp-content/themes/cordobo-green-park-2/archive.php on line 32

Warning: A non-numeric value encountered in /www/webvol34/an/96qmbdpibm1sspm/danielliljeberg.se/public_html/blog/wp-content/themes/cordobo-green-park-2/archive.php on line 32

Warning: A non-numeric value encountered in /www/webvol34/an/96qmbdpibm1sspm/danielliljeberg.se/public_html/blog/wp-content/themes/cordobo-green-park-2/archive.php on line 32
class="post-110 post type-post status-publish format-standard hentry category-c tag-c">

Objektorienterad utveckling i ANSI C

22 juli, 2010

Även om jag en gång i tiden började med, och länge utvecklade med, procedurella språk så har jag genom åren börjat tänka mycket mera objekt orienterat när jag utvecklar. Det började när man lärde sig C++ och har blivit ett intuitivt sätt för mig att se lösningar på mina utvecklingsproblem. För ett tag sedan fann jag mig dock i situationen att vara begränsad till ANSI C. Koden skulle kompileras på gcc och således är new, class och liknande bara att glömma. Mycket av koden på plats var skriven rent procedurellt, men den del försökte kapsla in olika delar genom att gruppera dem i olika filer osv. Jag fann det överraskande svårt att helt släppa det objektorienterade tänket och började istället att titta på vad jag skulle kunna göra för att iaf få in en del av de saker jag tycker om med objekt orienteringen i min kodning även i ren ANSI C. Detta är första gången jag gör detta, så jag lär mig och kommer på nya saker hela tiden och mycket kommer nog revideras. Men här följer lite tankar.

Arv


Arv kan till viss del fejkas genom att dina structar ser identiska ut på de delar som de har gemensamt och att alla specifika delar kommer sist i structen.


 

printStruct kommer nu kunna ta emot både foo och bar structar. Men nackdelen är att du själv måste typkasta din bar struct om du vill skicka in den till funktionen. Funktionen kan inte heller skriva ut strängen i en bar struct då det skulle bli problem om du i själva verket hade skickat en foo struct. Ett sätt att komma runt detta är att låta funktionen ta en void* istället, men då kan du ju verkligen skicka in vad som helst och du kan omöjligt veta vilken struct du verkligen tar emot. En “lösning” kan vara att ha ett typ fält i din struct. Du kan sedan låta funktionen kolla vilken typ det är och välja vad den skall göra på structen utifrån det.



 

Nu kommer funktionen att skriva ut strängen om det är en bar struct du skickar in. Självklart måste type sättas till rätt värde, något som jag sköter via new funktioner som skapar mna structar. Till exempel

Jag har hört rykten om att man skall kunna definera sin struct på ett sätt så att man faktiskt skulle kunna låta funktionen ta en pekare till “bas” structen, men detta är inget jag lyckats med. Om någon vet så hojta gärna till.

Privata variabler

Att ha en massa variabler i våra objekt som vi egentligen inte vill att änvändaren skall pilla på har vi alla varit med om. I C++ deklarerar vi dessa som private. Men i en struct i ANSI C så finns inte denna möjligheten. Vad du dock kan göra är att i din .h fil skriva


 

Och i din .c fil skriver du sedan

Nu kommer alla dina funktioner i din .c fil för objektet känna till hur din struct ser ut inuti, men för alla andra som bara har deklarationen i din .h fil att gå på så kommer medlemsvariablerna att vara gömda. Vi har nu lyckats återskapa lite av möjligheterna med privata variabler. Om du vill ha en statisk privat medlemsvariabler så åstadkommer du liknande funktionalitet genom att du deklarerar den utanför din struct i din.c fil.

Medlemsfunktioner

Medlemsfunktion är trevligt att ha om du tex har en array med pekare till dina structer som alla nu kan vara av lite olika typ. Men vi vet att alla skall köras genom en run funktion. Dock skall inte alla behandlas lika. Här kan vi göra som innan att kolla en type variabel i vår struct och utifrån den välja vad vi skall göra. Något som dock är snyggare är att använda medlemsfunktioner. Något som faktiskt även det går att uppnå med ANSI C.

I dina new funktioner för de olika “objekten” (som jag nu hellre vill börja kalla dem än structar… hehe) så tilldelar du funktionerna.

Sedan kan du i din main göra

Variabeln result kommer nu vara 1 då vi tilldelade runOne till vår run-funktion i konstruktorn och den funktionen returnerar 1. Om detta objekt var en del av en array av objekt hade vi kunnat loopa dem och köra deras respektive run-funktioner och var och en av objekten kunde i sin tur peka på helt egna implementationer av den funktionen.

Detta var bara lite snabba saker som jag kommit på under de senaste dagarna. Kom gärna med tipps och idéer. Och om ni finner detta intressant och vill ha mera av denna varan om jag kommer på mera saker så hojta till. Koden ovan är inte testkompilerad så kan vara några småfel här och där, men själva idén bör framgå.

Flattr this!