Kaikki on tälläistä kokeileet varmasti joskus, kääntyi linuxin gcc:llä -ansi vipulla, tiedä sitten mitä tuokin tarkoitti.
eipä ole destructoreitakaan, mut niitä nyt tekee kun viitsi.
/* * Dummy example about OO-programming in C * Author: Oleg Grenrus <phadej@gmail.com> */ #include <stdio.h> #include <stdlib.h> typedef enum {false, true} bool; /* virtual functions */ typedef enum {PRINT} Car_functions; /* parent class */ typedef struct __TCar { void (**_functions)(); int year; } *TCar; /* function declarations */ void TCar_print(TCar t); /* function array */ void (*TCar_functions[])() = { TCar_print }; /* child classes * * notice that parent fields are at the same place, important! */ typedef struct __TToyota { void (**_functions)(); int year; char *model; } *TToyota; void TToyota_print(TToyota t); void (*TToyota_functions[])() = { TToyota_print }; typedef struct __TVolvo { void (**_functions)(); int year; bool tractor; int wheels; } *TVolvo; void TVolvo_print(TVolvo t); void (*TVolvo_functions[])() = { TVolvo_print }; /* car constuctor */ TCar TCar_construct(TCar t, int year) { TCar _t; if (!t) _t = (TCar) malloc(sizeof(struct __TCar)); else _t = t; _t->_functions = TCar_functions; _t->year = year; return _t; } /* toyota constructor */ TToyota TToyota_construct(TToyota t, int year, char *model) { TToyota _t; if (!t) _t = (TToyota) malloc(sizeof(struct __TToyota)); else _t = t; /* parent constructor */ TCar_construct((TCar) _t, year); _t->_functions = TToyota_functions; _t->model = model; return _t; } /* volvo constructor */ TVolvo TVolvo_construct(TVolvo t, int year, bool tractor, int wheels) { TVolvo _t; if (!t) _t = (TVolvo) malloc(sizeof(struct __TVolvo)); else _t = t; /* parent constructor */ TCar_construct((TCar) _t, year); _t->_functions = TVolvo_functions; _t->tractor = tractor; _t->wheels = wheels; return _t; } /* car print */ void TCar_print(TCar t) { printf("Car\n year : %d\n", t->year); } /* toyota print, calls parent print too */ void TToyota_print(TToyota t) { TCar_print((TCar) t); printf(" mark : Toyota\n model : %s\n", t->model); } /* voldo print, calls parent print too */ void TVolvo_print(TVolvo t) { TCar_print((TCar) t); printf(" mark : Volvo\n tracktor : %s\n wheels : %d\n", t->tractor ? "yes" : "no", t->wheels); } /* abstract car print, dont care of type of car */ void Car_print(TCar t) { void (*fp)(TCar t); fp = t->_functions[PRINT]; fp(t); } /* example */ int main() { TCar cars[10]; int i; for (i = 0; i < 10; ++i) { if (i % 2) cars[i] = (TCar)TVolvo_construct(NULL, 1990+i, i & 0x2, i%4); else cars[i] = (TCar)TToyota_construct(NULL, 1980+i, "carina"); } for (i = 0; i < 10; ++i) { Car_print(cars[i]); } return 0; }
Jaa, noilla kommenteillako tästä piti jotain oppia?
Lyhyesti: jos halua oo:ta niin vaihtaa c++ ;)
Pidemmällä tavalla: jos katsoo mainia, niin alussa on tehty TCars array (T*** tyypit on oikeesti pointereita), ja siihen on sitten tehty volvoja ja toyotoja vähän eri parametreilla.
Kun kaikki on pointereita ja castataan oikeissa paikoissa niin kääntäjäkin tietää mikä tyyppi on menossa.
TCars, TVolvo ja TToyota on pointereita structeihin joissa kaikissa ekana jäsenenä on _functions, joka on pointeri funktio arrayhy.
year on TCarsissa joka on parent tässä esimerkissä, ja year peritään TToyotaan ja TVolvoon. Jotta tämä toimisi pitää lapsissa olla sama alku kuin emossa, samoilla offseteilla.
Moniperintä tässä ei oikein onnistu.
constructoreissa ekana parametrina on itse se tyyppi, koska sitä kautta voi kutsua parent-constructorin, niin kuin siellä näkyykin.
Sitten se hienous: tämä Car_print funktio ei sitten välitä mitä tyyppiä autot on vaan kutsuu sopivan print funkarin. Funktiopointerit on mapissa. Toinen ratkaisu olisi pitää funktiopointerit itse structissa, mikä olisi ainakin tilaavievämpi ratkaisu. Myös tarkasilmäiset huomaavat että esim nämä *_print funktiot voivat olla ainoiastaan samoilla parametreilla, koska nekin kerrotaan sille funktiopointerille.
Car_printissa käytetäänkin tavallaan turhaa pointeria, mutta ei taida hirveen helpolla saada funktiopointeri castattua ja kutsuttua kerralla. Ja kummiskin pitäisi kääntäjän tollaisen optimoida (en ole tarkistanut mitä mahtaa gcc generoida tästä).
Vähän muokkasin sitä olemaan fiksummin. nyt jokasessa oliossa on pointeri arrayhin jossa funkkkarit, vähän selvempää.
Mitä helvettiä "OO-ohjelmointi" on? (ei, en vaivaudu kuuklettamaan.)
Jotain infoa vois edes antaa, kuvauksesta ei saa mitään tietoa ohjelman tarkoituksesta...
En ole tietääkseni koskaan tuollaista kokeillut.
voi hitsi, en vaan tiedä suomalaisia termejä niin äh. minä en menetä tässä mitään.
oo = object oriented aka olio-
Oliopohjaisesta ohjelmoinnista muistelen puhuttavan.
EDIT: "vipulla" -> "vivulla" :3
njoo, mut ei otsikkoa ei voi muuttaa, et eletään tämän kanssa.
>>Lyhyesti: jos halua oo:ta niin vaihtaa c++ ;)
Heh, totta. Mutta tuosta voi olla hyötyäkin, jos koodaillaan esimerkiksi jotain laiteläheistä, ja jos kohdealustalle ei yksinkertaisesti ole C++-kääntäjää saatavana. Olio-pohjainen mallinnus tarjoaa kuitenkin usein huomattavia etuja. Mutta jos vain on mahdollista, niin kannattaa valita olio-ohjelmointiin tarkoitettu/kykenevä kieli.
>>Mitä helvettiä "OO-ohjelmointi" on? (ei, en vaivaudu kuuklettamaan.)
Jotain infoa vois edes antaa, kuvauksesta ei saa mitään tietoa ohjelman tarkoituksesta...
Kyllähän tuosta näkee ensi silmäyksellä mikä sen tarkoitus on... Jos et ole olio-ohjelmoinnista ikinä kuullut, niin voi voi, ja onnea ohjelmointiharrastukselle (harrastukseksi voi ilman OO:ta jäädä).
Aihe on jo aika vanha, joten et voi enää vastata siihen.