TDIU20 - Objektorienterad programmering i c++ - föreläsning 4 Pontus Haglund Department of Computer and information science
1 Vad gjorde vi förra gången? Felhantering Operatorer Typkonvertering 2 Grundläggande om pekare 3 New 4 Destruktorer 5 Composition
2 / 40 Dagens föreläsning 1. Pekare new delete avreferering adress nullprt 2. Objektorientering Composition Nästlad klass
1 Vad gjorde vi förra gången? Felhantering Operatorer Typkonvertering 2 Grundläggande om pekare 3 New 4 Destruktorer 5 Composition
4 / 40 Vad gjorde vi förra gången Kom ihåg att ni alltid kan gå tillbaka till förra föreläsningen och se slides i sin helhet. Felhantering Operatorer binära unära interna externa Typkonvertering static_cast operatorer konstruktorer
5 / 40 Felhantering i c++ Testar att göra övre blocket Vid fel (en throw) hoppa till ett av catch-blocken Fel kastas upp en nivå i programmet try //Försök göra //Fånga exception catch(logic_error& e) catch(...)
6 / 40 Att tänka på try är i princip lika snabbt som vilken annan kod som helst Exceptions är VÄLDIGT långsamma när du kastar dem Använd endast i exceptionella situationer Använd INTE exceptions som en styrstruktur Mycket långsammare Dåligt praxis
7 / 40 Binära operatorer Har 2 operander. Vår klass är vänstra. //Exempel c1 + c2; c3 = c1; cout << c3; //Hur c++ ser det c1.operator+(c2); c3.operator=(c1); cout.operator<<(c3); //Objektet är vänstersidan //I Complex.h class Complex public: //... Complex operator+(complex const& rhs); Complex& operator=(complex const& rhs); //... ; Ostream& operator<<(ostream& lhs, Complex const& rhs Men om objektet inte kan vara vänstra?
8 / 40 Unära operatorer Har 1 operand. Vår klass är den operanden. //Exempel c1++; //post ++c1; //pre --c1; //pre c1--; //post -c1; //??? //Hur c++ ser det c1.operator++(int); //? c1.operator++(); c1.operator--(); c1.operator--(int); //? c1.operator-(); //Objektet är vänstersidan //I Complex.h class Complex public: //... Complex& operator++(); Complex operator++(int); Complex& operator--(); Complex operator--(int); Complex& operator-(); //... ; postinkrement är lite av ett fulhack...
9 / 40 Typomvandling Att omvandla en typ till en annan Exempelvis göra om en int till en double Varför! Hur?
10 / 40 static cast Kontrolleras compile time Krävs att objektet vet hur det konverteras till typen eller visa versa string cs1 = static_cast<string>( Complex1, 3 ); Complex c1, 3; string cs2 = static_cast<string>( c ); Hur kan vi se till att Complex vet hur den skall konverteras till string?
11 / 40 Hur vet klassen? Genom att lägga till den operatorn i klassen. Objektet vet hur den kan konverteras till målet //Unary operator //Medlemsfunktion Complex::operator string() return to_string(); class Complex //... operator string(); operator int(); //... Observera: Ingen returtyp Fungerar för andra typer
12 / 40 Typkonverterande konstruktorer Målet vet hur objektet kan konverteras till sig konstruktorn sköter konvertering från en annan typ till din typ //h-fil class Complex //... // Konstruktor som tar en parameter av typen Complex(std::string const& str); //...
1 Vad gjorde vi förra gången? Felhantering Operatorer Typkonvertering 2 Grundläggande om pekare 3 New 4 Destruktorer 5 Composition
14 / 40 Minne Datorns minne löper från 0-N N = minnetsstorlek - 1 Består av bytes Siffran i intervallet är platsen, adressen 1 megabyte är 0 till 2 20-1 Vi kan visualisera minnet
15 / 40 Vad har en adress? Allt vi lägger i minnet har en adress Vanligtvis använder vi variabler för att komma åt den biten av minne Men vi kan också lagra och manipulera adresser // Ger oss en int-stor bit av minnet // Vi kan komma åt minnet med variabeln int var10; // Ger oss en char-stor bit av minnet // - char var2'h';
16 / 40 Lagra adress // Vad händer? #include <iostream> using namespace std; int main() int var17; int* ptrvar; cout << ptr << endl; // Vad händer? #include <iostream> using namespace std; int main() int var17; int* ptr&var; cout << ptr << endl;
17 / 40 Avreferera en adress #include <iostream> using namespace std; int main() int var17; int* ptr&var; cout << ptr << endl; #include <iostream> using namespace std; int main() int var17; int* ptr&var; cout << *ptr << endl;
18 / 40 Nullptr int main() int* ptrinullptr; cout << ptri << endl; 0 int main() int* ptrinullptr; cout << *ptri << endl; Segmentation fault nullptr, inte 0 eller NULL!
19 / 40 sizeof Storleken i chars (bytes), är en operator #include <iostream> using namespace std; int main() int var17; int* ptr&var; cout << sizeof(ptr) << endl; #include <iostream> using namespace std; int main() int var17; int* ptr&var; cout << sizeof(*ptr) << endl;
20 / 40 Stjärna och Ampersang Stjärna * Unär operator - avreferera Kan användas vid typer (int pekare) Ampersang & Unär operator - referens kan användas vid typer (string )
21 / 40 Stjärna och Ampersang cont. int var4; int* ptri&var; //typ och referens cout << *ptri; //avreferering //typ ostream& operator<<(ostream& lhs, Complex const& rhs) //...
22 / 40 Vad händer här? Ändras adressen eller vad som ligger på den adressen? int var42; int* ptri&var; *ptri = 109;
1 Vad gjorde vi förra gången? Felhantering Operatorer Typkonvertering 2 Grundläggande om pekare 3 New 4 Destruktorer 5 Composition
24 / 40 Vad gör new? Vilka delar av minnet allokeras till c++ vid start? New ger oss minne i heapen / free store Massor av ansvar...
25 / 40 new cont. #include <iostream> using namespace std; int main() int var17; int* ptri&var; int* ptr = new int17; ptr = new int[10]; cout << ptri << " " << ptr; Tappade vi just bort minne?
26 / 40 new cont. #include <iostream> using namespace std; int main() int var17; int* ptri&var; int* ptr = new int17; delete ptr; ptr = new int[10]; cout << ptri << " " << ptr; Har vi fixat det?
27 / 40 new cont. #include <iostream> using namespace std; int main() int var17; int* ptri&var; int* ptr = new int17; delete ptr; ptr = new int[10]; delete[] ptr; // varför är detta fel? cout << ptri << " " << *ptr;
28 / 40 new cont. #include <iostream> using namespace std; int main() int var17; int* ptri&var; int* ptr = new int17; delete ptr; ptr = new int[10]; cout << ptri << " " << *ptr; delete[] ptr; Nu har vi fixat det
29 / 40 void* och cast Undvik void* Vid hantering av pekare och new är vi på en låg nivå Typsystemet är vårt sista skydd Poängen är att ni ska låta bli i nästan alla fall void* pv = new int0; *pv = 2; // Error, varför? int pipv; // Error, varför? pv[1]; // Not subscriptable int* pi = static_cast<int*>(pv);
1 Vad gjorde vi förra gången? Felhantering Operatorer Typkonvertering 2 Grundläggande om pekare 3 New 4 Destruktorer 5 Composition
31 / 40 Block och destruktorer När en variabel går ut ur scope kommer den destrueras När ett objekt destrueras körs dess destruktor Rekursivt vector<int> v; v.push_back(4); cout << v.at(0) << endl; //Här destrueras v class Array public: Array();//Konstruktor ~Array();//Destruktor private: //array containing data int* data;
32 / 40 Block och destruktorer class Array public: Array(int size);//konstruktor ~Array();//Destruktor private: //array containing data int* data; Array::Array(int size) datanew int[size] Array::~Array() delete[] data;
33 / 40 Destruktor vs Konstruktor Det är Konstruktorns jobb att initiera datamedlemmarna korrekt. Det är destruktorns jobb att destruera datamedlemmarna korrekt.
34 / 40 Pekare och medlemmar class Array public: Array(int size);//konstruktor ~Array();//Destruktor void add(int index, int value); int get(int index) const; private: int* data; int main() Array* pa = new Array4; pa.add(0, 4); //funkar inte (*pa).add(0, 4); //Vad gör denna pa -> add(0, 4); //Vad gör denna
35 / 40 Destruktor vs Konstruktor konceptuellt Destructors are cenceptually simple but are the foundation for many of the most effective C++ programming techniques. The basic idea is simple: Whatever resources a class object needs to function, it acquires in a constructor. During the object't lifetime it may release resources and acquire new ones. At the end of the object'ts lifetime, the destructor releases all resources still owned by the object. Från: Bjarne S. 2014 Programming Principles...
1 Vad gjorde vi förra gången? Felhantering Operatorer Typkonvertering 2 Grundläggande om pekare 3 New 4 Destruktorer 5 Composition
37 / 40 Vad är composition Nyckelkoncept inom OOD och OOP Medlemmen är en del av objektet Medlemmen kan bara tillhöra ett objekt åt gången Medlemmens Lifetime styrs av objektet Medlemmen känner inte till objektet
38 / 40 UML Composistion visas med ifylld diamant Är en del av Kardinalitet
39 / 40 Vi tänker oss en stack Vad är en stack? Hur kan vi implementera en stack? Med pekare? Syntaktiskt- /Semanstiskt korrekt Head. Node Node. 5 10
40 / 40 Nästlad klass Tydligt relation mellan Element och Stack Inkapslad trots public åtkomst Vilken klass hör vad till? class Stack public: Stack(); Stack(std::initializer_list<int> il); ~Stack(); void push(int v); int pop(); std::string to_string(); bool empty(); //... private: struct Element public: Element* next; int value; ; Element* first; ; ostream& operator<<(ostream& lhs, Stack const& lhs);
www.liu.se