Ladda ner presentationen
Presentation laddar. Vänta.
1
TDP004 Objektorienterad Programmering Fö 8 Sammanfattning
2
Deklarationer/variabler/konstanter
Variabler kan initieras double salary; float distance = ; Konstanter och referenser måste initieras const double pi = ; int i = 10; int& j = i;
3
Typkonverteringar Konvertera mellan olika typer med static_cast<till typ>(variabel) Behövs vid tex float a = 7; float b = 4; int c = a / b; // c = 1 pga trunkering! Förväntat resultat fås med: int c = static_cast<float>(a) / static_cast<float>(b);
4
STL Standard template library. Containrar:
Sekventiella: vector, list, string. Associativa: map. Iteratorer (specialiserad pekare): forward- och reverse-iterator. Funktioner: Inbygga funktioner för sortering, sökning, flyttning av element, mm. Alla dessa använder iteratorer.
5
Översiktlig bild över iteratorer
begin() Forward iterator end() … rend() Reverse iterator rbegin()
6
Objektorientering Klasser
Byggstenen inom OO. Åtkomstdeklarationer Public, protected, private. Arv: Privat data/funktioner ärvs aldrig. Polymorfi. Inkapsling. Struct kan ibland vara ett alternativ till class. I en struct är åtkomsten som default public.
7
Exempel på klass I filen ExampleClass.h: class ExampleClass {
public: // Publik åtkomstdeklaration ExampleClass(int defaultID); // Konstruktor ~ExampleClass(); // Destruktor bool SetID(int aID); // Medlemsfunktioner. const int GetID() const; float f(float a, float b, float c) const; private: // Privat åtkomstdeklaration int m_ID; // Klassvariabel. … }; // Observera ; För det mesta definieras funktionerna i .cc/.cpp-filen. Detta är ett exempel på en klass. Klassdeklaration med class klassnamn. Åtkomstdeklarationerna public och private har vi gått igenom tidigare. Vi ser konstruktorn och destruktorn som publika funktioner, samt 3 andra andra publika funktioner SetID, GetID och f. Det finns även en privat medlemsvariabel m_ID som är en int.
8
Annat exempel på klass struct Position // Används för att spara en position. { double m_X; double m_Y; double m_Z; }; class Character public: Character(Position& aSpawnPos); ~Character(); void MoveToPosition(Position & aPosition); const Position& GetPosition() const; // OK att returnera en referens till en medlemsvariabel. // const gör att mottagaren inte kan ändra värdet. private: Position m_Position;
9
Åtkomst Med åtkomstdeklarationerna public, protected och private reglerar man åtkomst till klassens data och funktioner för andra klasser. Den egna klassen har alltid obegränsad tillgång. Public – fritt tillgänglig för läs och skriv. Private – ingen tillgänglighet alls. Protected – tillgänglig enbart för subklasser. I class är allt private som default.
10
Arv public: de ärvda funktionerna/datan behåller den åtkomst de hade i superklassen. protected: de ärvda funktionerna/datan blir protected i subklassen. private: de ärvda funktionerna/datan blir private i subklassen. Den ärvande klassen styr hur andra klasser ska komma åt de ärvda funktionerna. Vi ser att den ärvande klassen till viss del kan påverka hur andra klasser kan få tillgång till de ärvda funktionerna och variablerna, men de kan aldrig bli mera tillgängliga än de var i basklassen. Detta för att behålla abstraktion och inkapsling.
11
Konstruktor / destruktor
Konstruktor skapar objektet Initieringslistor. Behövs för medlemskonstanter och -referenser. Destruktor städar upp efter objektet. Om programmeraren inte skapar en konstruktor/destruktor skapar kompilatorn dessa. Kompilatorgenererad konstruktor använder inte initieringslistor. Virtuell destruktor viktigt vid arv. Kompilatorgenererad destruktor är inte virtuell.
12
Funktioner, forts. Deklaration, i h-filen: Definition, i cc-filen:
returvärde funktionsnamn(…); Definition, i cc-filen: returvärde klassnamn::funktionsnamn(…) { //Implementation } Med const& kan vi förhindra kopiering av datan(mha &) och hindra att funktionen ändrar på datan (mha const). Ex: int max(const int& a, const int& b); Värdet på parametrarna a och b kan nu inte ändras i funktionen max.
13
Funktioner En funktion gör en sak och bör göra det utan oönskade sidoeffekter. Returvärde void eller annan typ, inbyggd eller egendefinierad. Parameterlistan är den data som funktionen behöver från den anropande funktionen för att utföra beräkningen.
14
Virtuella funktioner virtual int f(…);
En virtuell funktion får (i C++) implementeras i basklassen, men kan överlagras av basklasserna. Virtuella funktioner är grunden för polymorfi. Funktionen implementeras kanske annorlunda i subklasserna än basklassen. Vilken funktion som anropas bestäms vid exekvering (dynamisk/sen bindning).
15
Shape Shape(double aHeight, double aWidth) { m_height = aHeight; m_Width = aWidth; } virtual double Calculate Area() = 0; Abstrakt basklass. Rectangle double CalculateArea() { return m_height * m_Width; } Triangle double CalculateArea() { return (m_height * m_Width ) / 2.0; } Enkelt klassdiagram. Subklasserna definierar funktionen CalculateArea() på olika sätt. Konstruktorer etc utelämnade. m_height och m_width är medlemsvariabler.
16
Polymorfism vector<Shape*> shapesVector;
Shape* shape1 = new Triangle(…); Shape* shape2 = new Rectangle(…); shapesVector.push_back(shape1); shapesVector.push_back(shape2); shapesVector.push_back(…); Ex 1: for(i = 0; i < shapesVector.size() ; ++i) { cout<< shapesVector[i]->CalculateArea() << ” ”; /* Anropar korrekt CalculateArea(), vi vet inte vilken implementation innan anropet sker. */ } Ex 2: shape1->CalculateArea(); //Anropar CalculateArea() i klassen Triangle. shape2->CalculateArea(); //Anropar CalculateArea() i klassen Rectangle. Fördelen med detta är att vi kan skapa olika Shapes och sedan anropa CalculateArea på dessa Shapes utan att i förväg veta vilken funktion som kommer att exekveras. I exemplet så gör vi just detta och sparar dem i en vector med Shape som element. Sedan itererar vi igenom denna vector och anropar CalculateArea för alla Shapes i vectorn. Korrekt implementation av CalculateArea kommer att anropas, men vi vet inte vilken implementation det är eftersom det kan finnas olika Shape i vectorn.
17
Polymorfism, forts. Vilken funktion som exekveras vid anrop till CalculateArea() avgörs vid exekveringen, sk dynamisk/sen bindning. En icke-virtuell funktion har sk statisk/tidig bindning: det bestäms vid kompilering vilken funktion som kommer att anropas.
18
Rent virtuella funktioner
virtual int f(…) = 0; Får ej implementeras i basklassen, måste implementeras i subklasserna. En klass med minst en rent virtuell funktion blir en abstrakt klass. Det är omöjligt att skapa en instans av en abstrakt klass.
19
Multipelt arv En klass kan ärva från flera olika basklasser.
Var försiktig med multipelt arv i allmänhet, pga ”diamond pattern”.
20
virtual f(int a, int b) = 0;
C int f(int a, int b) { return (a * b); } B int f(int a, int b) { return (a + b) / 2; } D D* d = new D(); d->f(1, 3); ??? Vad händer då funktionen f anropas i klassen D? Detta utseende i arvshierarkin kallas för ”The diamond pattern”.
21
Inkapsling Data och beräkningar kapslas in i funktioner och implementationen göms. Den anropande klassen behöver inte veta några detaljer om implementationen. Privat data och publika interface. Inkapsling är ett viktigt koncept inom OO.
22
static Static-funktioner hör till klassen, kan anropas även om det inte finns någon instans av klassen. Dessa kan enbart anropa andra funktioner som inte tar this som parameter (ex: Init-create från Fö 9). Static-klassvariabler – enbart en upplaga. Initieras utanför alla funktioner. Ex: int ExampleClass::staticVariable = 10; Minne för static medlemsvariabler allokeras enbart en gång.
23
Pekare, * Objekt som pekar på ett minne.
Används bla för dynamisk minneshantering. Ex: int* p1; float* p2; vector<int*> vp; /* vp är en vector som innehåller pekare till int.*/ ExampleClass* myClass = new ExampleClass(); En pekare måste inte, men bör initieras. Man kan kontrollera om en pekare är giltig genom jämförelse med NULL.
24
Använda pekare Om man har en pekare till ett objekt och vill anropa dess funktioner används notationen: variabelnamn->funktionsnamn(parametrar) Ex: ExampleClass* myClass = new ExampleClass(); myClass->func(1.1, 3.5, 5.7) Läser lokal variabel med liknande syntax. int id = myClass->m_ID; Nu kommer vi till det intressanta, hur man använder pekare. Om vi har en pekare till ett objekt kan vi anropa dess medlemsfunktioner och komma åt dess medlemsvariabler genom notationen ->. Se exemplet på hur det går till.
25
Referens & Alternativ till pekare. ”A reference is an alias”
En referens måste initieras. int i = 1; int& intRef = i; /*intRef refererar nu till variabeln is värde. */ All operationer på en referens är egentligen operationer på den underliggande objektet. ”A reference is just another name for an object” En referens får inte vara ogilitig. Det går inte att kontrollera om en referens är giltig. Medan en pekare är ett begrepp som vi måste aktivt dereferera för att komma åt det underliggande objektet så är alla operationer på en referens egentligen operationer på objektet, automatiskt. Vi kan se referensen som ett alias till objektet. En referens måste alltid initieras till adressen av en annan variabel/konstant av korrekt typ. Vi kan exempelvis inte initiera/tilldela en referens till ett värde direkt. OGILTIGT!! int& intRef = 1; Det finns dock undantag till regeln om att en referens måste initieras, och det är om en referens är en medlemsvariabel. Då måste referensen initieras i klassens konstruktor, vilket vi kommer att beskriva i en senare föreläsning. Varför vill man då ha referenser? Förrutom de välkända skälen att få en snabbare exekvering genom att undvika minneskopiering så kan man även använda dem för att kunna ha tillgång till samma variabel/objekt på liknande sätt som pekare.
26
Använda referenser Om man har en referens till ett objekt kan man anropa dess funktioner med variabelnamn.funktionsnamn(parametrar) Ex: ExampleClass myClass2 = &myClass; myClass2.func(1.1, 3.5, 5.7); Läser lokal variabel med liknande syntax. int id = myClass.m_ID; Det vara lite allmänt om referenser, nu till hur man använder dem. Om man har en referens till ett objekt kan man använda . punktnotation för att anropa medlemsfunktioner, komma åt medlemsvariabler etc. I exemplet initierar vi referensen med adressen av pekarens objekt. Vi kan sedan anropa funktionen f i myClass2.
27
Minneshantering Allokera nytt minne och skapa nya objekt med new.
MyClass* m_class = new MyClass(); Ta bort instansen och återlämna minnet med delete. delete m_class; m_class = NULL; // Behövs inte men ger möjligheten att jämföra med NULL. Vi behöver bara använda delete på minne som har allokerats med new.
28
Minneshantering C++ har tre olika sorters minneshantering:
Statiskt minne Globala och namespace-variabler, static variabler. Automatiskt minne/stack Funktionsargument och lokala variabler. Free store/heap Minnet allokeras med new. Eventuella minnesläckor finns här.
29
Översiktlig bild över minnet
kod Stacken växer neråt med ökande antal ”stack frames”. statiskt minne stack Heapen växer uppåt med mera dynamiskt allokerat minne (new/delete). heap
30
Frågor? Resten av tiden till frågor.
Liknande presentationer
© 2024 SlidePlayer.se Inc.
All rights reserved.