Kaukonäkökenttä eli C++ tutti numero 6 ====================================== OSA VI Matti osaa monta sanaa, Matti osaa monta sanaa, Matti osaa monta sanaa, Matti osaa monta sanaa, Matti osaa monta sanaa, Matti osaa monta sanaa, Martti osaa monta sanaa, Matti osaa monta sanaa ulkoa, Matti osaa monta sanaa, Matti osaa monta sanaa, Matti osaa monta sanaa, Matti osaa monta sanaa, Matti osaa monta sanaa, Matti saa monta sanaa, Matti osaa monta sanaa, Matti osaa monta sanaa, Matti osaa monta sanaa, Matti osaa monta sanaa, Matti osaa monta sanaa, Matti osaa monta sanaa, Matti osaa monta sanaa, Matti osaa monta sanaa, Matti osaa monta sanaa, Matti osaa, Matti osaa monta sanaa, Matti osaa monta sanaa sanoa, Matti osaa monta sanaa, Matti osaa monta sanaa. Tuon alkujuonnon kirjoitti nimeltämainitsematon Matti-niminen henkilö. Matti on poikkeuksellisen lahjakas ja osaa kirjoittaa monta erilaista sanaa ja muodostaa kokonaisia lauseita. Harva nelkytäkuusvuotias pystyy samaan! Napsi Mopsi nakkeja! Disclaimer ---------- Tässäpä ei ole disclaimeria tai mitään muuta varoitusta, koska sellaiset on todettu täysin turhiksi. Tai no ei oikeasti ole, joten kaipa tähän pitää pieni sitten kirjata. Enpäs siis ota vastuuta esimerkkien toimivuudesta tai asioiden oikeellisuudesta. Pitäisi varmaan muuten keksiä hörpötinhärpätin, joka tuottaisi automaagisesti sopivammanpuoleista tutoriaalin täyteainesta, siis välipuheenmuotoisentapaista pohdintaa ja puhelulörpöttelyä. Onkkelmanahan tuollaisessa olisi oikeammanpuoleisten lauserakenteiden muodosteleminen, sanastovermehet elikkätä pitäs tietää sanojansa, niiden sanojen tarkoituksenpuoleinen, etteistä ihan sekokielätänsä kirjoitteles. Sittensä voisis olla tähän tyyliin sopivammanpuoleisia päättehiä ja sananväännöksiänsä, jotkas vientävät sanansa mitä erikoisempiin asentoihin sekäs muotoihinsa. Tietenkäänsä ei pidä unohdella, notta ihan arvallansa ei voi heitellä sanojansa tahi lausehia ympäriinsä vaan pitäisi ollansa jokin edes hieman loogisemmanpuoleinen aiheistuspiiri noissa. Niin, ettäs siinäs teille tekemistä ja projektiansa, jolla saatten hianot taitonne käyttöönsä. Tai sitten ideoidaan vieläs pari muuta, kun ei oles mukavata, jos onpi sitten ylimonta tuollaista tuttigeneraattorintapaista. Jokus voisi muutensta tehdä semmosen ohjelmaisen, jokas pärjäisi Turingin testissänsä eikäs immeisenpuoleiset sitten tajuaisi sen olevan koneentapainen. Siihens kun tuollaisen hianon tekstinvääntövermehen lisäilettes, niin johan ootte onnistunehet tehtävässänne. Sitten vielä yksi ideanpuoleinen, nottas voisi sellaisen viennellä, ettäs se parsisi tästäs tutoriaalintapaisesta sittens ihan kelvollisenmuotoista suoamenkieltä. Niin, nottas ei tekijän hieanoja vientelyjä eikäs määritelmäntapaisia sinnes. Tämäs kun ei oikeinsta ole asiallisenpuoleisessa muodossaan. Ja koskas täälläs on nuita esimerkkilöitä, niin niihin sen ei pitäisi mennä koskeskelemaan, tai no voisis se niissä olevia kommentinpuoleisia muunnellas. Muttas nyh onpi varmaans aiheellisenpuoleista siirtyä seuravaan kappaleenmuotoiseen. Noin. Ja kaikille tiedoksi vielä, että tätä saa levitellä vapaammanpuoleisesti, aivan kuten naapurin naapuri saa levitellä omia antejaan, kunhan ei ihan julkeasti mene levittelemään. Tai no kyllä tätä saa levittää kun ei sitä ole toistaiseksi laissakaan kielletty. Tai no on, sillä tämähän on teos ja tekijänoikeuden alainen, mutta kun näistä teoksista saa määrätä se tekijänoikeuden haltija, joka sattuu olemaan minä, niin minäpä päätänkin, että tätä saa levitellä. Ei kyllä menis läpi tämä selitys siinä naapurin naapurin tapauksessa, vaan vankilaan pistäsivät tai ainakin sakkoja antasivat. On kyllä ihme touhua. Mutta enpä voi mitään, niin on joku minua viisahampi mennyt päättämään. Tosiaankin semmoinen lisäys vielä, että se paritus on kieällettyä niin eipä mennä sutenööriperkeleet perimään tämän levityksestä maksua elikkäs ilmahteeksi pitääpi siirrellä muille immeisille. Jäädäänpä luokalle! ------------------- Eli palataan olio-ohjelmoinnin pariloiseen ja miettikäämme näitä rakenteenpuoleisia ja määrittelyvermehiä enempi ja vähempi, jos sattuupi olemaan laiskemmanpuoleinen ihmisvätysolio. Kaikki kiiruhtaa nyt olioita katsomaan! Oliot on hauskoja, mutta niitä ei saa ruokkia! Selitetäänpä melkein heti alkuunsa tarkemmin, mitä nuo eri määreet elikkäs private, protected ja public tarkoittaapi. Elikkätä public on sellainen, jota voi mikä tahi kuka tahansa käsitellä. Private tarkoittaapi sitten vain kyseisen luokan käytettävissä olevaa vermehettä. Siihen ei sitten pääse suoraan käsiksi kuin nimenomaisen luokan metodit (itse kutsuvan metodin näkyvyydellänsä ei ole väliä). Viimeisenänsä on sitten protected, joka onpi kyseisen luokan sekä sen aliluokkien käytössänsä. Kätevätäpätevätä, jos peritytetynmallisen luokan metodit tarviipi jotain yläluokkansa muuttujaa tahi niin päin pois. Toki voisi tehdä erilliset julkiset metodit, jotka käsittelee tuota muuttujaa epäsuorasti, muttas silloinhan mikä tahansa voisi noita metodeja käytellä tuon muuttujan muuttelemiseen ja lukemiseen, joka ei välttämättä ole tarkoituksemmanpuoleista ja -mukaista. Niin, maanantaikappaleet tulee kalliiksi, koska niitä voidaan valmistaa vain kerran viikossa! Ja vastoin kaikkia odotuksia tämä tutoriaali kohtaa loppunsa ennen aikojaan, sillä nyt loppus kaikki suunnitellummanpuoleinen asia! No okei, puhutaan sitten paskeloista loppututti. Näin. Konstruktorit ja periyttäminen on mieälenkiintoinen yhtälöinen. Silläs periytettyä luokkaansa luodessa joudutaan luomaan esiintymä sen kaikista yläluokistansa. Muttas mitäs konstruktoria sielläs yläluokissansa kutsutaan? Noh, oletuksena on yläluokannimi() elikkäs normaali, parametritön, vaihtoehtoinen. Muttas jos tahdotaankin sinne parametrillista kutsua, niin tehdään temppu. Kappas, esimerkki lentääkin suoraan meitä kohtii kiihtyvällä vauhdillansa! ---[ luoja.cpp ]--- #include using namespace std; class a { private: int i; protected: int j; public: a() { i=1; j=0; cout << "a()" << endl; } a(int t) { i=t; j=0; cout << "a(int)" << endl; } a(char* t) { i=0; j=0; cout << "a(char*): " << t << endl; } virtual inline void tulosta() { cout << i << ", " << j << endl; } //Koska i on yksityinen muuttuja, sen arvo eivät pysty lukemaan muut //kuin tämä luokka. Siki erillinen metodi sen lukemiseksi. inline int getI() { return i; } }; class b : public a { private: int k; public: //Alustetaan muuttujan k arvoksi 0 b():k(0) { j=3; cout << "b()" << endl; } //Luodaan a-luokan esiintymä parametrilla t ja alustetaan muuttujan //k arvoksi t b(int t):a(t),k(t) { j=4; cout << "b(int)" << endl; } b(char* t) { k=0; cout << "b(char*): " << t << endl; } virtual inline void tulosta() { cout << getI() << ", " << j << ", " << k << endl; } }; int main() { cout << "Luodaan luokan a esiintymät:" << endl; a a1; a a2(5); a a3("ta"); cout << endl << "Luodaan luokan b esiintymät:" << endl; b b1; b b2(5); b b3("tb"); cout << endl << "Kutsutaan luokan a esiintymien tulosta()-metodia:" << endl; a1.tulosta(); a2.tulosta(); a3.tulosta(); cout << endl << "Kutsutaan luokan b esiintymien tulosta()-metodia:" << endl; b1.tulosta(); b2.tulosta(); b3.tulosta(); return 0; } ------------------- Hui, hai! Niin, luontokappaleiden käyttäminen esimerkeissänsä voi johtaa vaikkapas siihen, notta joku luontoaktivisti tuleepi tuonne ikkunan alle tallomaan naapurin petunioita ja huutelemaan, notta ei saa eläinkokeita tehdä tätä tutoriaalinsta kirjoitettaessa. Tämäkös sitten vaarantaa mahdolliset jatkojalostustoimenpiteet ensimmäisen osan eläinesimerkkilöille. Muttas emmehän me ole aaltopahvista, joten uhkarohkeasti tehkäämme norsu- ja lammas-luokat! (Eläimiä ei ole vahingoitettu tätä tutoriaalia tehtäessä, paitsi ehkä sikoja ja lehmiä. Tuo sillä perustella, että allekirjoittanut teki jauhelihakastiketta sika-nauta -jauhelihasta. Eläinuhreihin laskettakoon myös yksi banaanikärpänen, kumiankka ja mahdollisesti toinen tai jopa useampi sika, sillä allekirjoittanut nautti kinkkuviipaleen voileivän päällä. Mainittakoon vielä, että kumiankan henkeä ei riistettyä vaan sitä käsiteltiin kovakouraisesti, jolloin se vingahti). ---[ elain.cpp ]--- /* Jos luulitte, notta tässä on esimerkki, petyitte pahemman kerran. Voinen * paljastaa, notta tässä ei ole, eikä tule olemaan esimerkkiä. Syynä lienee * se, notta tänä on maailman helpoin homma ja C++ tuttinsa kunnolla * imeskelleet kyllä pystyvätten tarvittaessa tällaisen luomaan. * Jos suurta (yli yksi) kysyntää ilmenee, voinen fakkiin eli FAQ:n eli UKK:n * eli Usein Kysyttihin Kysymyksiin vastauksen liittää, mutta eieieiei. * Oottepa pällejä ettekä ole oppineet mitään. Lukekaa tutoriialit vielä * kerran uudelleen, niin joo... */ ------------------- Hökkökkööö. Olo on mitä hassuimmanpuoleisin. Allekirjoittanut olionpuoleinen on valveskellut nyh sittens 22 tuntia putkeensa, ja tuo sleep()-metodi tahtoisi kovin kovasti tulla suoritusvuoroiseen, jotensa lueskelkaa vaikka edellistä esimerkkilöistä tarkkemmanpuoleisesti tai imeskelkää vanhemmanpuoleisia tutintapaisia. Tauko XIV (se on neljästoista!) Ohjelmaesimerkki ---------------- Jo muinaiset roomalaiset tiesivät, kuinka monta on paljon ja paljonko on monta. Nyt pari vuosituhatta myöhemmin laskekaamme paljonko nykyjärjestelmämme mukaiset luvut olivat Rooman aikaan. Eli jos minulla on kuusi C++ tutoriaalia, niin montako C++ tutoriaalia minulla olisi Rooman valtakaudella? Kah, tehkäämme ohjelmainen, joka laskeepi tuon kaiken minun, sinun, hänen, meidän, teidän ja heidän puolestansa. Ja jos aikaa jää, kertokaamme opettavainen eläintarina jäniksestä, joka hävitti silmälasinsa. Tai sitten tehkäämme siitä runontapainen kertoelma! ---[ rooma.cpp ]--- #include #include using namespace std; class Rooma { //Ikuinen kaupunki private: static const char merkit[]; unsigned int numero; string haeNumero(unsigned int n, unsigned int i); public: Rooma() { numero = 0; }; Rooma(unsigned int num) { numero = num; }; inline void asetaNumero(unsigned int num) { numero = num; } Rooma& operator=(unsigned int num); string muunna(); }; //Mielenkiintoinen stattisen arvon alustustapa... //Kirjaimet vastaavat numeroita: 1,5,10,50,100,500,1000 const char Rooma::merkit[] = {'I','V','X','L','C','D','M'}; Rooma& Rooma::operator=(unsigned int num) { numero=num; return *this; } //Muunna arabialainen (1..9) numero * 10^i roomalaiseksi string Rooma::haeNumero(unsigned int n, unsigned int i) { if (i<1) return "ERR!"; i--; i*=2; //Numerot 1..3 -> I,II,II / V,VV,VV / X,XX,XX / ... if (1<=n && n<4) { string tmp=""; for (unsigned c=0; c IV, XL, ... else if (n==4) { return merkit[i]+string("")+merkit[i+1]; } //Numero 5 -> V, L, ... else if (n==5) { return string("")+merkit[i+1]; } //Numerot 6..8 else if (5 IX else if (n==9) { return merkit[i]+string("")+merkit[i+2]; } return "ERR!"; } //Muuntaa koko numeron string Rooma::muunna() { string tmp; vector nums; //Hajoitetaan numero for (unsigned int i=numero; i>0; i/=10) nums.push_back(i%10); //Muunnetaan osa kerrallaan roomalaiseksi for (unsigned int i=nums.size(); i>0; i--) //Jos jakojäännos==0, ei kyseistä numeroa tarvi tulostaa if (nums[i-1]!=0) tmp+=haeNumero(nums[i-1],i); return tmp; } int main() { Rooma r(4); cout << r.muunna() << endl; for (unsigned int i=1; i<15; i++) { r=i; cout << i << "==" << r.muunna() << endl; } r=2004; cout << r.muunna() << endl; r=1999; cout << r.muunna() << endl; r=444; cout << r.muunna() << endl; return 0; } ------------------- Kutsuvieras Thorin pistää päälle mekkalan, hillitkää häntä hyvät jumalat! Kai koko pihan hajottaa ja aasat itkee: "julmaa". Ei Lif tästä hätkähdä vaan Magnin päätä taputtaa ja sanoo: "rök ska du ha!" Ähölämliarpöks -------------- Otsikko tarkoittaapi selevällä suoamen kieälellä, notta salausohjelma. Siis semmottinen, joka muuntelee selväkielisen datanpuoleisen ihan sekokieleksi eikäs kukaan saa siitä sitten selkoista ilman salaisen puoleista sanaa tahi lauseistusta. Maanmaino vermes tietenkin tuo onpi, ja voipi sitten tunkea piiloonsa vaikkapa lauseen: "Avantouimarien vuotuinen kokous järjestetään Köyliön järven jäällä sijaitsevalla avantouimapaikalla tiistai-iltana kello kuuden aikaan. Sauna on lämmin. Oma pullo/pyyhe mukaan." Tokis tuon salaaminen on kansallinen tietoturvariski eikäs tietenkään kovin hyväksytä, kun ei saa herra isoveli valvoa viestintää, jotenska ovat rajoittaneet edellytyksiämmä tuon salata. Niin ja perkeleet kehittelevät vielä kvanttitietokoneita, joilla saapi viestit ja niiden salaukset auki tuosta vaan. Muttas! Vastatkaamme haasteentapaiseen suurin ja sankemmanpuoleisin joukkioin sekä ryppäin ja salatkaamme viestit yhä paremmin ja sekavammin, eikäs kenenkään ulkoisen puolisen henkilöisen tule saamaan tuota selville! Pistäkäämmä barrikaadit rajalle ja raja tähän! ---[ salaa.cpp ]--- #include #include using namespace std; class Salaaja { protected: string passwd; public: Salaaja() { passwd="dummy"; } Salaaja(string sala) { passwd=sala; } virtual ~Salaaja() {}; virtual string salaa(string data); virtual string pura(string data); inline void setPass(string sala) { passwd=sala; } }; class Salaaja2 : public Salaaja { public: virtual ~Salaaja2() {}; virtual string salaa(string data); virtual string pura(string data); }; string Salaaja::salaa(string data) { string tmp=""; unsigned int c=0; for (unsigned int i=0; i=passwd.length()) c=0; tmp+=char(data[i])^p; } return tmp; } string Salaaja::pura(string data) { return salaa(data); } string Salaaja2::salaa(string data) { string tmp=""; unsigned int c=0; for (unsigned int i=0; i=passwd.length()) c=0; tmp+=(int(data[i])-p)%256; } return tmp; } string Salaaja2::pura(string data) { string tmp=""; unsigned int c=0; for (unsigned int i=0; i=passwd.length()) c=0; tmp+=(int(data[i])+p)%256; } return tmp; } int main() { Salaaja* sala = NULL; string s="Tämä on suuri salaisuus! Shh!"; for (unsigned i=0; i<2; i++) { switch (i) { case 0: sala=new Salaaja(); break; case 1: sala=new Salaaja2(); break; default: cout << "Ihme" << endl; } sala->setPass("MinunSalaSana"); string tmp=sala->salaa(s); cout << "Merkkijono on salattu: alkuperäinen==salattu? " << (s==tmp) << endl; cout << "Purettu salaus: " << sala->pura(tmp) << endl; cout << "alkuperäinen==purettu salaus? " << (s==sala->pura(tmp)) << endl; cout << endl; } return 0; } ------------------- Näinikään! Tuosta jäi selvästikin puuttumaan kaikkea hassua. Mutta eipä annaeta sellaisten haitata. Mutta annanpa vihjettä, notta kannattaa vertailla vielä eri salaajilla salattua vermettä, esim. Salaaja a("a"); Salaaja2 b("a"); ja sitten cout << a.salaa("moi")==b.salaa("moi") << endl; Voinen paljastella, notta eipä ole samat. Tuossansa ensimmäisessä salaajassansa on käytetty perinteistä XOR-salausta eli käytetään binääristä joko-tai -vermestä, jossa siis arvojen jokaiselle bitille: 0^0=0, 1^0=1, 0^1=1, 1^1=0. Näin siis esimerkisti 101010^111000=010010. Tätähän voidaan sitten salaukseen käyttää, silläs 010010^111000=101010. Toisessa on hieman erilaisempi vermes, elikkäs käytetään vähentely ja plus-laskujansa. Esim. 10-4=6. 6+4=10. Tähän vielä ympärikiepsautus eli otetaan jakojäännös: 10-15=-5, -5%20=15. Ja 15+15=30, 30%20=10. Jo keisarin esikuvainen elikkätä Caesar sitten keksi oman vermeen, joka oli muuten sama, muttas siinä tuo avain oli samas aina. Tässä vaihdellaan avaimen arvoa joka kerta. Eli joo. Melkeistä vaikea purkaa. Leikkäkääpä itsenne kanssa tai sitten tuon koodin kanssa itseksenne ja keksikää salailuvermes, jota ei kukaan pysty purkaamaan ilman oikeanpuoleista salaista sanaa. Muttas nyt kasvit lakkasivat kasvamasta, kaikki tuhat erilaista, samaan aikaan. Tämä tarkoittaa vain yhtä asiaa! Sanan saan kai sanoa, ah? Hetki jo on, vielä aikaa, vielä, vielä, nyt! Miksi meitä kaikki tuijottaa? Loppusanat ---------- Mitä näät tänään? Etkö mahdu kenkään? Monestiko pitää asia toistaa, jotta sen jaksaa huomenna muistaa? Onko kello? Hei! Eli tämä oli siis C++ tutoriaalisarjan viimeinen osa. Enkä tee enää uusia osia, vaikka kuinka kinuaisitte. No sellainen optio pidetätköön, notta FAQ eli UKK eli usein kysytyt kysymykset voidaan toteuttaa, muttas se ei ole varsinainen tutoriaali. Jos jaksan, haluan ja näen tarpeelliseksi, saatan toteuttaa C++ tutoriaalien selitysteoksen, jossa raotelmoin ihmeisille kaikkia ihmeitä, joita tänne olen kirjannut. Siis tarkoittanen nyt nuita muita asioita, jotka joistakuista saattavatten näyttää enempi tahi vähempi järkeenkäyvilta. Muttas jokaisen takanansa on ainakin jotain ideanpuoleista, ainakin vähän, vaikka ihan vaan pikkiriikkisen, aivan mahdottoman pienesti. Mutta onpa jotakin. Toisaalta voipi olla taasn järkevää antaa vaan olla ja ihmisten pähkäillä maailman menoa ja saattaa tämän tutoriaalisarjan tekijä lepäämään täysihoitolaitoksiinsa. Tosinsa sinne joutuakseen pitäisi olla vaarallisenpuoleinen otus esimerkiksi itsellensä ja/tai muille. Ehän mää semmottinen ole, ainakaan paljon, enkö, hihih, vai, hähähähäh, körr. Vaaraksihan nämä tutoriaalit ovat ihmiskunnallensa. Täältä minä tulen, oi avosylin minut vastaanottakaa! Lehmät hirnuu ja hunajaa kantavat, kukasta kukkaan lantaa antavat! Liikaa - olisiko liikaa, kaikki - ei vähempää? Tätä tutoriaalisarjaa oli ilo tehdä, eikä työstäminen koskaan tuntunut hankalalta, epämiellyttävältä tai pakonomaiselta. Tarkoitus ei ollut tehdä virallista, ehdottoman opettavaa, kuivaa materiaalia, joka olisi jäänyt pölyyntymään tietoverkon uumeniin - eikä tämän totisesti pidäkään! Tutoriaalisarjan kirjoitustyyli on omalaatuinen ja suuri osa minua itseäni, joten näiden arvostelu opetusteoksena pitäisi olla rangaistava teko. Moni voi ihmetellä, miksi tällainen? Vastauksia on kaksi, tekijän itsensä ja sananvapauden takia. Nämä tutoriaalit ovat toimineet minulle ikään kuin terapiana ja rentouttavana itsensä toteuttamiskanavana. Olen ottanut huomioon, että näitä tulee joku ehkä joskus lukemaan. Niin uskon ja toivon. Näistä lukijoista löytyy varmasi joku, joka vetää herneen, ilmaa tai kuorma-auton nenäänsä. Heitä varten on omistettu tästä tutoriaalisarjasta kokonainen osa. Varmasti joku tahtoo sensuroida nämä ja siistiä paskaa kieltää ja vittumaista asennetta ja rasistisia kommentteja. Niin kauan kuin on tuollaisia vouhottajia minä jaksan jatkaa. Ja tiedän, että voin sanoa mitä tahansa, kirjoittaa mitä tahansa, ja nauraa päälle - eivätkä he voi mitään. Siksi, siksi sanonkin heillä tämän, kaiken, mitä he ovat pelänneet: kiitos. Loppuun lausuttakoon kiitosken sanainen eri henkilöitymille. Ensinnäkin Heikki Höijärille kiitos ja kumarrus yhteistyöstä. Toinen kiitos menee Tuomas Starckille määrittämättömistä syistä. Kolmas kiitoksen sana John Fundlelle eräistä ohjelmointineuvoista. Vielä nimetty kiitos Jaakko Pellavalle ideoista. Kiitos myös vanhemmilleni, joita ilman tämä tutoriaalisarja ei olisi ollut mahdollinen. Eksyi metsään tyttö tuo, eksyi metsään suden luo. Itki tyttö suruissaan, sudelta anoi armoa. Susi viekas, katala, söi tytön suuhunsa. Samassa metsän reunassa oli jänisparka huolissaan: "voi tätä surua, missä on minun kakkulat?" Hui kauhua, voi kamala, voi vaikka suden suuhun joutua! Eikös siinä samassa tule puun taka hukka kamala, jänön kauhuun pelottaa, ei pelkoon kuitenkaan ole aihetta - täynnä vatsansa on lihaa ihmisen, pienen tyttö poloisen. Lahjan tahtoo kanille antaa, tytöltä jäi yhdet lasit turhaan... Kahvitauko (c) kello nelejä - eiku vuosi, Joro (Joro on olevinaan Jouni Roivas, http://roivas.org, sähköinen kusti toimittaa paketit perille osoitteeseen jroivas@iki.fi ja telepatiaa saa käyttää myös.) P.S. Ruotsalainen Johan Linbunten otti minuun yhteyttä ja pyysi saada kääntää nämä tutoriaalit ruotsiksi. Suostuin pyyntöön tietyin ehdoin ja tiedossa on siis ruotsinkielisille lukijoille suurta mannaa C++ tutoriaalien muodossa. P.P.S. Eräs tuttavani on aloittanut tämän tutoriaalin innoittamana oman, vuoden 2004 aikan ilmestyvän, C++ tutoriaalisarjansa työstämisen, joten tämä ei jää tähän, ei koskaan!