310 likes | 433 Views
Föreläsning 6. Klassmallar. Templates kan givetvis även användas för klasser Standardutseende. template < class T> // Klassdefinition (*.h) class C { returtyp metod(parametrar…); ... };. template < class T> // Def. av metod (*.h) returtyp C<T>::metod(parametrar…) { ... }.
E N D
Klassmallar • Templates kan givetvis även användas för klasser • Standardutseende template<class T> // Klassdefinition (*.h)class C { returtyp metod(parametrar…); ...}; template<class T> // Def. av metod (*.h)returtyp C<T>::metod(parametrar…){ ... }
Templates i templates • ”Templatiserade” klasser kan ta templates som argument • std::vector<Point<float> > vektor; • Observera; mellanslag mellan de avslutande hakarna!
Egna Namespaces • För att skapa ett eget namespace att lägga klasser i använder man nyckelordet namespace • Standardutseende Namespace jms{template<class T> class Matrix { returtyp metod(parametrar…); ... };}
Egna Namespaces • 3 olika sätt att komma åt klassen Matrix • jms::Matrix<int> matrix; • Använder uttryckligen en klass i ett specifikt namespace • using namespace jms;Matrix<int> matrix; • Använder hela jms namespace (risk för kollisioner) • using jms::Matrix;Matrix<int> matrix; • Använder endast en delmängd av jms namespace (Matrix)
typeid • I vissa fall vill man kunna avgöra ett objekts egentliga klass • Detta kan lösas med operatorn typeid void fordonsinfo(Fordon * fp){if (typeid(*fp) == typeid(Personbil)) cout << ”fp är en personbil” << endl;elseif (typeid(*fp) == typeid(Buss)) cout << ”fp är en buss” << endl;elseif (typeid(*fp) == typeid(Lastbil)) cout << ”fp är en personbil” << endl;};
Upcast • Vi har tidigare sett att man kan behandla specialiserade klasser på samma sätt som mindre specialiserade klasser void main(){ Personbil bil; // Personbil skickas som ett Fordon fordonsinfo(&bil); } void fordonsinfo(Fordon * fp){ // Vi kan anropa Fordons alla medlemmar // Vi kan INTE anropa Personbils medlemmar!};
typecast • Vi kan använda explicit typomvandling för att konvertera åt andra hållet • Vi kan konvertera från vilken klass som helst till annan valfri klass • Ingen säker metod eftersom vi teoretiskt sett kan typomvandla från ett ”Däggdjur” till en ”Bil” vilket ger en överhängande risk för programkrasch
typecast void main(){ Horse horse; Car * car1 = &horse; // kompilatorn varnar Car * car2 = (Car*)&horse; // accepteras car2->ShiftGear(3); // PROGRAMKRASCH!}
Downcast • För att göra en typsäker typomvandling finns i C++ specialoperatorn dynamic_cast • C++ kontrollerar att objektet verkligen är av rätt typ för att en säker typomvandling skall kunna ske • Klassen måste vara polymorf (virtuella metoder) void fordonsinfo(Fordon * fp){ Personbil * bil; bil = dynamic_cast<Personbil*>(fp);if (bil) cout << ”fp är en Personbil”;else cout << ”felaktig typomvandling”;}
Felhantering • Felhantering i C är ganska besvärlig • Oftast returneras felmeddelanden från funktioner. Returvärdena måste sedan kontrolleras samt hantera eventuella fel • Om en funktion returnerar ett objekt är det svårt att bestämma när ett fel har uppstått. • Kan ge konstiga konstruktioner
Exempel (felhantering) void main(){// division med noll!float resultat = dividera(5.0f, 0.0f);// vad är ett felaktigt returvärde i // detta fall?} float dividiera(float taljare, float namnare){// hur hanterar vi division med noll?return taljare/namnare;};
Exempel (felhantering C) void main(){int resultat;int retur = dividera(5.0f, 0.0f, &resultat);if (retur = 0)// Division med noll!!} int dividiera(float taljare, float namnare, float result){if (taljare == 0)return 0; *result = taljare/namnare;return 1;};
Exempel (felhantering C++) void main(){int result;try { result = dividera(5.0f, 0.0f); } catch (char * str) {// Division med noll!!}} float dividiera(float taljare, float namnare){if (taljare == 0)throw ”Division by zero”;return taljare/namnare;};
Exceptions • Exceptions kan användas när det uppstår undantagsfel i programmet • Exempelvis om minnet tar slut, inläsning av en trasig fil, avbruten kommunikation m.m. • Exceptions ger fördelen att programmeraren kan förutsätta att allt går bra, men ifall det skulle uppstå problem så kan dessa hanteras
Exceptions • Ett exception slängs med operatorn throw • Valfritt objekt kan slängas • Klasshierarkier med olika Exception-objekt kan med fördel användas • Objektet returneras bakåt i anropshierarkin tills det fångas av en ”try – catch” rutin
Exceptions • Exceptions kan ge en felhantering på hög nivå • Felet behöver inte tas omhand i den felande funktionen eller i den direkt anropande funktionen • Hantering av fel är inte alltid möjlig i den direkta närheten där felet uppstår, men kan med exceptions hanteras högre upp i anropshierarkin
Exceptions • Standardbiblioteket har en definierad klasshierarki av exception-objekt exception logic_error runtime_error bad_alloc bad_cast out_of_range length_error range_error invalid_argument domain_error overflow_error underflow_error
Flera catch-uttryck void main(){try { File file(”c:\kalle.txt”); string str = file.ReadString(); } catch (OutOfMemoryException e) {// Slut på minne vid inläsning} catch (BadFileFormatException e) {// Felaktigt filformat} catch (Exception e) {// Andra standardfel som kan uppstå} catch (...) {// Fånga ALLA andra fel här (DivisionByZero m.fl.)}}
Flera catch-uttryck • Ett try-catch block kan ha flera catch-uttryck för att hantera flera olika fel • Endast ett catch-uttryck exekveras • Det första som matchar • Ellipsis (…) fångar alla fel • Om denna används bör den vara sist av catch-uttrycken
Släng undantagsfel • Syntax: • throw 4; • throw Klass(); • throw Klass(konstruktorparametrar); • Flera olika undantagsfel (objekt) kan slängas från en metod, men endast en i taget
Skicka vidare exceptions • En metod kan behöva fånga undantagsfel utan att kunna hantera felet • Exempelvis kan en metod avallokera minne för att undvika minnesläckage. För att sedan vidare hantering av felet skall ske så kan metoden skicka vidare felet med ”throw;” i catch-uttrycket
Skicka vidare … void function(){try { File file(”c:\kalle.txt”); string str = file.ReadString();} catch (...) { cout << ”Fel uppstod vid läsning” << endl;throw; // Skicka vidare}}
Vad händer vid exceptions? • Stack unwind – anropsstacken plockas ned • Objekt på varje nivå destrueras • Minnesläckagerisk • Om man allokerat minne måste detta avallokeras. Lämpligen genom att fånga felet, avallokera minnet samt skicka exception-objektet vidare.
Händelsestyrd programmering • Programmet är passivt • Programmet ligger inaktivt så länge ingenting händer • Lämpliga metoder anropas automatiskt när vissa kriterier är uppfyllda • Musrörelser, Knapptryckningar m.m.
Fördelar • Programmet slipper ”pollande” loopar, dvs loopar som hela tiden ligger och kollar om någonting skall göras. • Mindre processoråtgång • Viktigt i multiprocessystem (windows) • Programmet kan koncentrera sig på att utföra uppgifter istället för att undersöka vad som skall göras
MFC • Microsoft Foundation Classes • Klasspaket (framework) • Klasser för att programmera windows-program • Bygger på Win32 API (application programming interface) • Händelsestyrt
Viktiga MFC-Klasser CObject Basklass som alla MFC-klasser ärver från CCmdTarget Sköter hantering av meddelanden inom/mellan objekt CWnd Basklass som hanterar alla grafiska ytor Alla fönster ärver från denna CFrameWnd Hanterar utritning av innehållet i CFrameWnd CView CWinThread Trådhantering (multithreading) MFC-applikationer börjar i denna klass CWinApp CDocument Motsvarande Modellen i Model-View-Controller CDC Används vid all utritning till CWnd-objekt
Nyttiga MFC-Klasser CPoint Point-klass, liknande de som skapats i laborationerna CSize Hanterar storlekar (kompletterar CPoint) CRect Beskriver rektanglar och dess operationer CString Stränghantering, liknande std::string CTime Operationer för tidsberäkningar
MFC-Wizard • I Visual C++ får man följande upplägg av MFC Wizard (projekttyp) • Klass härledd från CWinApp • Startar och initierar windows-programmet • Klass härledd från CFrameWnd • Sköter allt specifikt för applikationsfönstret • Klass härledd från CView • Sköter all utritning av data från CDocument • Klass härledd från Cdocument • Hanterar all applikationsdata
Projektskelett (Bounce) CBounceApp Skapar CMainFrame CBounceDoc Innehåller Känner till CBounceView