Föreläsning 2
Allmänt STL genererar varningar i Visual C++ –”#pragma warning (disable : 4786)”
Typen Boolean C++ har en ny datatyp; bool –Kan vara true eller false void main() { bool finished = false; while(!finished) {... finished = true; } }
Inline Förbättrad variant av makro Funktioner ”klistras” in i källkoden Undviker de negativa effekterna av funktionsanrop inline int max(int a, int b) { return a>b ? a:b; } #define max(a,b) (a>b ? a : b)
Klasser En klass är: –Användardefinierade datatyper –Logiskt sammanhängande data & operationer –Beskrivning av en samling objekt med likadana egenskaper –“En struct innehållande funktioner, inte bara data”
Klasser i C++ (kap. 7) Används som en “form att framställa objekt från”. Beskriver hur objektet skall se ut (datamedlemmar/dataattribut) –Storlek, färg, vikt, hastighet, tillstånd… Beskriver vad man kan göra med objektet (metoder/operationer) –Skapa, ta bort, flytta, starta, stanna…
C-strukturer (struct) struct Size { int width; int height; }; int SizeGetWidth(const struct Size * s); int SizeGetHeight(const struct Size * s); void SizeSetWidth(struct Size * s, int w); void SizeSetHeight(struct Size * s, int h); struct Size storlek; SizeSetWidth(&storlek, 6); SizeSetHeight(&storlek, 10);
Klasser i C++ (Size.h) class Size { public: int GetWidth(); int GetHeight(); void SetWidth(int w); void SetHeight(int h); int m_width; int m_height; }; Size storlek; storlek.SetWidth(6); storlek.SetHeight(10); Klassdeklarationen läggs i header-filen
Klasser i C++ (Size.cpp) Klassdefinitionen läggs i cpp-filen #include ”Size.h” int Size::GetWidth() { return m_width; } int Size::GetHeight() { return m_height; } void Size::SetWidth(int w) { m_width = w; } void Size::SetHeight(int h) { m_height = h; }
Klassens beståndsdelar Datamedlemmar –Motsvarar ”typedef struct” i C –Aggregat & association Metoder –Funktioner inuti en klass
Datamedlemmar Aggregat – ”By value” –Har-relation –Objekt som ingår som delar i en instans Association – ”By reference” –Känner till-relation –Pekare –Referens
Metoder Fungerar som funktioner i C –Returvärde –Parametrar –C-program, for, while, switch m.m. Dessutom är medlemsvariablerna för objektet åtkomliga som om de vore lokala variabler
Övning Laboration 2 A –Skapa klassen Point –Skapa lämpliga metoder och medlemsvariabler –Skapa både.h och.cpp filer
Medlemsåtkomst Klassnivå – ”::” –int string::length() {... } Objektnivå –Referenser och ”riktiga” objekt – ”.” String s; s.length(); –Pekare – ”->” String * s; s->length();
Skapa egna klasser Gränssnitt inte definitivt –Ett objekts gränssnitt är inte entydigt definierat –Vi väljer vilka egenskaper och vilket beteende vi vill belysa –Beroende på sammanhang
Exempel (gränssnitt) class Car { public: void Run(); void Stop(); bool m_running; }; class Car { public: void Run(); void Stop(); bool m_running; }; class Car { public: void Owner(Person & p); Person & Owner(); Person m_owner; }; class Car { public: void Owner(Person & p); Person & Owner(); Person m_owner; };
Konstruktorn (kap. 7.3) ”metod” som anropas automatiskt när objektet skapas Används för att initiera objekt Kan ta emot parametrar –Size s(10,5); –ofstream file(”c:\\temp\\fil.txt”); Kan överlagras, dvs det går att ha flera konstruktorer till en klass
Konstruktorn forts. Har samma namn som klassen Ser ut som en metoddeklaration förutom att den inte har ett returvärde –Size(int width, int height) {... } Undviker följande scenario Size s; s.Create(10,5);
Destruktorn (kap. 7.4) ”metod” som anropas automatiskt när objektet tas bort Används för att ”städa upp” efter ett objekt –Avallokera minne –Släppa resurser Har inga parametrar Har samma namn som klassen fast med ett ’~’ framför
Exempel (size igen) class Size { public: Size(int w, int h); ~Size(); int GetWidth(); int GetHeight(); void SetWidth(int w); void SetHeight(int h); int m_width; int m_height; };
Exempel (size forts.) // Konstruktor Size::Size(int height, int width) { m_height = height; m_width = width; } // Destruktor Size::~Size() { // Avallokera eventuellt minne m.m. }
Övning Utöka klassen Point med att lägga till lämpliga konstruktorer och destruktor
Doctor Snuggles har en rymdraket som heter Spruttibangbang Skapa klassen DreamyBoomBoom Lägg till lämpliga metoder och datamedlemmar Källa Övning
Kopieringskonstruktor (kap ) Det finns en speciell konstruktor som kopierar hela objekt av samma typ Size s1(10,5); Size s2(s1); // s1 kopieras till s2 Size s2=s1; // s1 kopieras till s2 // Defaultimplementation Size::Size(Size const & s) { m_width = s.m_width; m_height = s.m_height; }
Kopieringskonstruktor forts. Konstruktorn finns alltid i C++ –Default-beteende: kopiera alla datamedlemmar element för element. –Kopieringskonstruktorn för datamedlemmar används vid elementvis kopiering Överlagra konstruktorn då speciell behandling krävs –Ex. om minne skall allokeras för varje enskilt objekt, annars kopieras minnespekaren
Kopieringskonstruktor forts. Kopieringskonstruktorn används –Då nyskapat objekt tilldelas ett objekt –Då objekt skickas som parametrar –Då objekt returneras från metoder // Kopieringskonstruktor anropas Point p2 = p1; // Kopieringskonstruktor används inte p2 = p1;
Typomvandlingskonstruktor (kap ) Konstruktor med EN parameter –eventuellt fler, om de har defaultvärden Gör följande uttryck möjliga –string s = ”implicit typkonvertering”; // Typkonverteringskonstruktor string s = ”sträng”; // Resulterar i string s = string(”sträng”);
Typomvandlingskonstruktor forts. Kan medföra problem –Implicit konvertering kan ske utan programmerarens avsikt –Använd ”explicit” framför konstruktorer som har en parameter och som inte skall fungera som typomvandlingskonstruktor explicit Text(int n);
Övning Lägg till kopieringskonstruktor i Point Är det lämpligt att ha en Typomvandlingskonstruktor?
Inkapsling (kap. 6.4) Mål - att kapsla in data i objekt –Objektet bör vara den ende med kunskap om vilka data som existerar inom objektet –Resterande delar av programmet skall ej vara beroende av hur ett objekt är sammansatt –All dataaccess skall gå via gränssnittet
Exempel (inkapsling) class Point // Kartesiska koordinater { public: SetPosition(int x, int y); private: int m_x; int m_y; }; class Point // Polära koordinater { public: SetPosition(int x, int y); private: int m_vinkel; int m_radie; };
Inkapsling forts. Resultat –Gränssnittet bestämmer hur ett objekt skall användas –Innehållet/uppbyggnaden av en klass kan ändras vid behov –Förändringar i en klass skall inte påverka programmets beteende –Modularitet
Tillgänglighet (kap. 9.3) Begränsning av tillgång till datamedlemmar och medlemsfunktioner –Public –Protected –Private
Public Används för det gränssnitt som skall visas utåt från en klass –Vanligtvis för metoder i en klass –Undvik i största möjliga grad för datamedlemmar
Protected Används för data och metoder som inte skall kunna kommas åt utifrån –Används i samband med arv –Oftast för metoder som är interna hjälpfunktioner som inte skall visas utåt.
Private Data och metoder är endast åtkomliga inifrån det objekt där de är deklarerade –Använd för datamedlemmar –Använd för interna medlemsfunktioner –För att gömma och hindra tillgång till ”hack”
Övning Uppdatera Point så att alla medlemmar har korrekt tillgänglighet
Konstanta objekt och variabler Begränsa möjligheten att ändra på variabler och objekt Länk till en djupare diskussion om ”const” – lite/const-correctness.html
Konstanta variabler (1/2) float pi = ; // pi får ändras float const cpi = ; // cpi får ej ändras float * pip = &cpi; //Icke tillåtet float const* pip = &cpi; //Tillåtet char *buf="Hello"; char * const buffer = buf; // Konstant pekare buffer = buf; // Icke tillåtet i kompilator buffer[0] = 0; // Tillåtet?? char const* const myProg = argv[0]; myProg[0]='\0';
Konstanta variabler (2/2) char buf[10]="Hello"; char * const buffer = buf; // Konstant pekare //nu finns minnet kvar. buffer = buf; // Icke tillåtet i kompilator buffer[0] = 0; // Tillåtet char const* const myProg = argv[0]; myProg[0]='\0'; // Icke tillåtet i kompilator
Konstanta objekt Point point; // point får ändras Point const cpoint; // cpoint får inte ändras cpoint.SetX(10); // Fungerar inte int x = cpoint.GetX(); // Detta då? // cpoint ändras inte av att vi hämtar en kopia av X-värdet. Hur skall vi få detta att fungera? // Deklarera metoden “const” i klassen int Point::GetX() const {... }
const … forts. Var generös med användning av ”const” –Det är enklare att ta bort const- begränsningar än att lägga till nya i efterhand –Gränssnittet skall förhoppningsvis ge ledtrådar om objektet/metoden/variabeln skall vara const eller inte –Get-metoder är const –Set-metoder är inte const
Övning Uppdatera Point med korrekt användning av const på de ställen där det passar
Statiska medlemmar (kap 8.5) Kan användas som vanliga medlemmar Behöver dock inget objekt för att anropas/ändras void main() { xxx::klassmetod(5,5); // Eller xxx x; x.klassmetod(5,5); }
Klassvariabler Deklareras på samma ställe som datamedlemmar (i klassen), men existerar endast i en version. Alla instanser av en viss klass delar på samma variabel Kan liknas vid en global variabel
Klassvariabler forts. // Deklareras i klassen class xxx {... protected: static int m_klassvariabel; }; // Definieras i cpp-filen int xxx::m_klassvariabel = 0;
Klassmetoder Statiska metoder som är C++ närmsta motsvarighet till funktioner i C Endast parametrar, globala variabler och klassvariabler är åtkomliga i klassmetoder Deklareras som vanliga metoder i en klass med tillägget ”static” Definieras på samma sätt som metoder
Klassmetoder forts. // Deklareras i klassen class xxx {... public: static int klassmetod(int a, int b); }; // Definieras i cpp-filen int xxx::klassmetod(int a, int b) {... }
Block & minsta möjliga scope Ett block definieras av innehållet mellan tecknen ’{’ & ’}’ –Gäller rekursivt (block i block) –Variabler är giltiga i det block de deklarerats i –Giltiga i ”underblock” (block i block) God sed är att använda sig av minsta möjliga scope för lokala variabler
Exempel (block) Lokala variablers destruktor körs när variabeln kommer ”out-of-scope” void main() { int a = 3; { int a = 5; cout << a; // skriver ut ”5” } cout << a; // skriver ut ”3” }
Exempel 2 (block) void main() { { ofstream file(”c:\\temp\\fil1.txt”); file << ”fil1”; } // här körs destruktorn för file // file existerar inte här file << ”detta fungerar inte”; { ofstream file(”c:\\temp\\fil2.txt”); file << ”fil2”; } // här körs destruktorn för file }
Mallar (Templates) Parametriserade funktioner och klasser Kompilatorn gör en avancerad search/replace i källkoden Uttrycker funktionaliteten i funktioner/metoder utan typberoenden Typsäker vid kompileringen
Funktionsmallar template inline T max(T const & a, T const & b) { return a>b ? a:b; } void main() { int i = max (7, 1); float f = max (3.6f, 7.1f); }
Klassmallar (.h) template class Size { public: T GetWidth(); T GetHeight(); void SetWidth(T w); void SetHeight(T h); T m_width; T m_height; }; void main() { Size s; s.SetWidth(20.1); s.SetHeight(10.8); }
Klassmallar (.cpp) #include ”Size.h” template T Size ::GetWidth() { return m_width; } template T Size ::GetHeight() { return m_height; } template void Size ::SetWidth(T w) { m_width = w; } template void Size ::SetHeight(T h) { m_height = h; }
Övning Gör om Point till att vara en parametriserad klass
Klasser återblick informationsdöljande (information hiding) – mitt och ditt, kontroll, bemästra komplexitet –lokalitet, lätt hålla ihop Gränssnitt mot omvärlden (interface) Bibliotek, tillverkare och användare –OBS! Klasser och deras interaktion behöver dokumenteras