TDDC76 - Programmering och Datastrukturer

Relevanta dokument
Objektorientering - Arv och polymorfi

TDIU20 - Objektorienterad programmering i c++ - föreläsning 6

TDDC76 - Programmering och Datastrukturer

Objektorientering - Arv och polymorfi. Eric Elfving Institutionen för datavetenskap

TDDC76 Programmering och datastrukturer

Programmering i C++ EDA623 Arv. EDA623 (Föreläsning 6) HT / 42

Innehåll. Konstruktorer vid arv Regler för basklassens konstruktor. Konstruktorer vid arv. Konstruktorer vid arv. Konstruktorer vid arv

Innehåll. 1 Kort om dynamisk polymorfism. 2 Arv i C++ 3 Multipelt arv. 4 Något om statisk polymorfism. class Container {

TDDC76 - Programmering och Datastrukturer

Arv. Objektorienterad och komponentbaserad programmering

Introduktion till arv

Innehåll. Pekaren this Självreferens. Klasser Resurshantering, representation. Överlagring av operatorer. Överlagring av operatorer

Innehåll. Typomvandlingar (casting) Implicita Typomvandlingar. Typomvandlingar (casting) Implicita Typomvandlingar

Del2 Klasser, medlemmar och arv Ämnesområden denna föreläsning:

TDIU01 Programmering i C++

TDIU20 - Objektorienterad programmering i c++ - föreläsning 4

Operatoröverlagring. endast operatorsymboler definierade i C++ kan överlagras = += -= *= /= %= ^= &= = <<= >>= < > <= >= ==!= && > ->*, [ ] ( )

Introduktion. Klasser. TDP004 Objektorienterad Programmering Fö 2 Objektorientering grunder

TDDC76 - Programmering och Datastrukturer

Programmering i C++ EDA623 Objektorienterad programutveckling. EDA623 (Föreläsning 5) HT / 33

Dynamisk bindning och polymorfism

TDDE10 m.fl. Objektorienterad programmering i Java Föreläsning 6 Erik Nilsson, Institutionen för Datavetenskap, LiU

Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 4 Jonas Lindgren, Institutionen för Datavetenskap, LiU

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 4 Erik Nilsson, Institutionen för Datavetenskap, LiU

C++ Objektorientering - Klasser. Eric Elfving Institutionen för datavetenskap

5 Arv och dynamisk bindning FIGUR

Klasshierarkier - repetition

Klasser. Kapitel 2. Kapitel 2 - Klasser, medlemmar och arv. Klasser. Klasser Medlemmar Arv

Skapa, kopiera och destruera klassobjekt

Del3 Klassanvändning, operatorer och pekare Ämnesområden denna föreläsning:

C++ Objektorientering - Klasser. Eric Elfving

Programsystem konstruktion med C++ (2D1387) Innehåll. övning 2 klasser och arv

Innehåll. Pekare Exempel

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 2 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Tentamen i TDP004 Objektorienterad Programmering Lösningsförslag

Kapitel 6 - Undantag

Tentamen EDAF30 Programmering i C++

Kapitel 3. Synlighet. Kapitel 3 - Klassanvändning, operatorer och pekare. Synlighet

Innehåll. Pekare Exempel

Tillämpad programmering

Trädtraversering. Binärt träd. Trädtraversering djupet-först. Trädtraversering bredden-först

TDDE10 m.fl. Objektorienterad programmering i Java Föreläsning 6 Erik Nilsson, Institutionen för Datavetenskap, LiU

Objektorienterade programmeringsspråk. Objektorienterade språk. Den objekt-orienterade modellen. Jämför med icke-oo

KLASSER. Inkapsling Abstrakt datatyp Public och private. Klassmedlemmar Datamedlemmar Exempel Funktionsmedlemmar

UML. Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2016

TENTAMEN CD5250. Objektorienterad programutveckling med C++, 5p. Datum: , Tid: 14:00-19:00

Synlighet. Namespace Scope-operatorn Klasser Vänner

Programmering i C++ EDAF30 Dynamiska datastrukturer. EDAF30 (Föreläsning 11) HT / 34

Innehåll. Resurshantering. Resource handles. Minnesallokering. Minnesallokering Exempel: allokering på stacken. 6. Resurshantering

Lektionsuppgifter. TDDI14 Objektorienterad programmering. Lektionsplanering Lektion Lektion Lektion

Innehåll. Resource handles. Resurshantering. Minnesallokering. Minnesallokering Exempel: allokering på stacken. 7. Resurshantering, Felhantering

Polymorfi. Objektorienterad och komponentbaserad programmering

Arv bakgrund (kap. 9)

Innehåll. Introduktion till objektorientering. OOP (objektorienterad programmering) Objekt, instanser, klasser

Programsystemkonstruktion med C++: Övning 2. Karl Palmskog september 2010

Objektorienterad Programmering (TDDC77)

UML. Klassdiagr. Abstraktion. Relationer. Överskugg. Överlagr. Aktivitetsdiagram Typomv. Typomv. Klassdiagr. Abstraktion. Relationer.

Föreläsning 8 - del 2: Objektorienterad programmering - avancerat

I STONE. I Variabler, datatyper, typkonvertering. I Logiska och matematiska uttryck. I Metoder-returvärde och parametrar. I Villkorssatser if/else

Generiska konstruktioner. Kursbokens kapitel 13

Programsystemkonstruktion med C++

Föreläsning 3: Abstrakta datastrukturer, kö, stack, lista

Programmering i C++ EDA623 Mallar. EDA623 (Föreläsning 12) HT / 29

Innehåll. dynamisk bindning. och programmering CRC) u Arv, polymorfi och

Innehåll. 1 Typdeklarationer och typomvandling 2 Resurshantering. 3 Objektorientering, kort repetition. 4 Klasser

Innehåll. Typomvandlingar (casting) Implicita Typomvandlingar. Typomvandlingar (type casts) Explicita, namngivna typomvandlingar (C++-11)

Outline. Objektorienterad Programmering (TDDC77) Att instansiera en klass. Objekt. Instansiering. Åtkomst. Abstrakt datatyp.

Outline. Objektorienterad Programmering (TDDC77) Signatur. Klassen calculator. Överlagring (overloading) Arv (inheritance) Ahmed Rezine

TDIU20 - Objektorienterad programmering i c++ - föreläsning 3

Objektorienterad Programmering (TDDC77)

Högskolan Dalarna sid 1 av 5 Data-avdelningen Hans-Edy Mårtensson

TDIU01 - Programmering i C++, grundkurs

Arv. Fundamental objekt-orienterad teknik. arv i Java modifieraren protected Lägga till och modifiera metoder med hjälp av arv Klass hierarkier

Idag. Javas datatyper, arrayer, referenssemantik. Arv, polymorfi, typregler, typkonvertering. Tänker inte säga nåt om det som är likadant som i C.

Övriga byggstenar. Övriga byggstenar. Några tips under programutveckling. Beroenden Pekare till funktioner Typkonvertering

Tentamen i TDP004 Objektorienterad Programmering Teoretisk del

Klasser. Det är egentligen nu som kursen i programmeringsteknik börjar..., s k objektorienterad programmering.

Objektorienterad programmering Föreläsning 12. Copyright Mahmud Al Hakim

TDIU01 - Programmering i C++, grundkurs

Konstruktion av klasser med klasser

Tommy Färnqvist, IDA, Linköpings universitet

Classes och Interfaces, Objects och References, Initialization

Föreläsning 8. Arv. Arv (forts) Arv och abstrakta klasser

1 Namnkontroll (NameControl)

Objektorienterad Programkonstruktion. Föreläsning 4 8 nov 2016

F8: Typkonvertering i C++

TDDE10 TDDE11, 725G90. Objektorienterad programmering i Java, Föreläsning 3 Erik Nilsson, Institutionen för Datavetenskap, LiU

Högskolan Dalarna sid 1 av 5 Data-sektionen Hans-Edy Mårtensson

OOP Objekt-orienterad programmering

Arv och polymorfi. Lite terminologi; Basklass eller superklass: En klass som fungerar som bas för vårt arv. Vi skapar nya klasser utifrån den.

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 2 Erik Nilsson, Institutionen för Datavetenskap, LiU

TDIU01 - Programmering i C++, grundkurs

Arv: Fordonsexempel. Arv. Arv: fordonsexempel (forts) Arv: Ett exempel. En klassdefinition class A extends B {... }

Objektorienterad Programmering (TDDC77)

Innehåll. Exceptionella händelser (exceptions, undantag ) Felhantering Tre nivåer av felhantering: Nivå 2: exceptions (eller returvärde)

DAT043 - Föreläsning 7

Kopiering av objekt i Java

Det objektorienterade synsättet. Objekt. Datorprogrammet kan uppfattas som en slags modell av den verklighet programmet skall samverka med.

allokeras på stacken dynamiskt new delete

Vad är en klass? Övning 2. Konstruktorer. ffl copy-konstruktorn tar en instans av klassen som. ffl default-konstruktorn tar inga argument och kan

Transkript:

TDDC76 - Programmering och Datastrukturer Objektorientering - Arv och polymorfi Klas Arvidsson Institutionen för datavetenskap

1 / 33 UML UML är ett grafiskt språk som (bland mycket annat) används för att beskriva relationen mellan klasser i objektorienterade system. Vi tar upp fyra olika relationer och hur de ritas: Arv: En Person är en Människa med allt det innebär. Komposition: En Person har en Kropp. Aggregation: En Person kan ha Klädesplagg. Association: En Person kan använda Hyrbil.

2 / 33 UML relationer som figur/graf (analysresultat) Human Body Person Cloth. RentalCar

3 / 33 UML klasser i större detalj När de klasser vi behöver är identifierade kan vi specificera dem i större detalj. Datamedlemmar, medlemsfunktioner och dess åtkomst specificeras: + anger public - anger private # anger protected : typ anger datatyp/returvärde

4 / 33 UML relationer som figur/graf (designresultat) Human # iq : int Cloth vector - name : string Person + put_on(cloth const& c) : bool + drive(rentalcar const& c) : bool RentalCar - top_speed : int Body. + groom() : void + ignition(bool on) : void + accelerate(int delta) : void + turn(double angle) : void

5 / 33 UML relationer C++-kod class Person : public Human // inheritance, is public: Person() : Human(), body}, clothing} } void put_on(cloth const&); void drive(rentalcar&); // association, knows about private: Body body; vector <Cloth > clothing; }; // composition, always part of // aggregation, can come and go

6 / 33 En (annan) Person att utgå från class Person public: Person(string n, string p) : namen}, phonep} } string get_phone() const return phone; } void print_info(ostream& os) const; private: string name; string phone; };

7 / 33 Arv till Employee Vi vill nu skapa en anställd. En anställd är en person med lön och arbetstelefon. Hur skapar vi den klassen när vi redan har en person? Vi kan kopiera och klistra till helt ny klass Employee. Det innebär att allt framtida arbete med Person-klassen manuellt måste dupliceras till Employee. Vi kan låta en ny Employee-klass innehålla en Person som datamedlem. Det innebär att vi måste skapa nya funktioner i Employee för att komma åt allt i Person.

8 / 33 Arv till Employee Vi kan använda arv för att berätta för kompilatorn att en ny klass Employee automatiskt är allt som en Person är. Person blir basklass och Employee blir härledd klass (alternativt subklass): class Employee : public Person public: Employee(string n, string p, string w, int s) : Personn,p}, work_phonew}, salarys} } string get_phone() const; string get_home_phone() const; string get_work_phone() const return work_phone; } int salary() const; private: string work_phone; int salary; };

9 / 33 Anrop av basklass från subklass En härledd klass har direkt alla datamedlemmar och medlemsfunktioner som finns i basklassen. Det går även att explicit ange att basklassens medlem ska användas. Men inte ens en härledd klass har tillgång till basklassens privata medlemmar! string Employee::get_phone() const return Person::get_phone() + ", " + work_phone; } string Employee::get_home_phone() const return phone; // Compilation error, private to Person! }

10 / 33 Åtkomst av basklass från subklass Vi kan i basklassen ge härledda klasser tillgång till medlemmar med nyckelordet protected! class Person public:... private: // endast för klassen själv string name; protected: // endast för klassen själv och härledda klasser string phone; };

11 / 33 Statisk bindning I C++ används statisk bindning om inget annat anges. Det innebär att datatypen som anges i programkoden avgör vilken funktion som anropas. Person kim"kim", "2146"}; Employee sam"sam", "2490", "1234", 40000}; Person& refsam}; cout << kim.get_phone() << endl; // 2146 cout << sam.get_phone() << endl; // 2490, 1234 cout << sam.get_work_phone() << endl; // 1234 cout << ref.get_phone() << endl; // 2490 cout << ref.get_work_phone() << endl; // Compilation error! sam.print_info(cout); // Sams uppgifter skrivs ut på cout kim.print_info(cout); // Kims uppgifter skrivs ut på cout

12 / 33 Import eller borttagning av basklassmetoder Det går att välja och vraka vilka medlemsfunktioner från basklasserna som ska finnas i den härledda klassen. // Tillfällig vikarie class Substitute : public Employee public: using Employee::Employee; // Ger konstruktor motsvarande Employee using Person::get_phone(); // Väljer versionen i Person string get_work_phone() const = delete; }; Substitute s"toni", "4711", "", 60000}; s.get_phone(); // The version in Person s.get_work_phone(); // Compilation error!

13 / 33 En härledd klass har flera datatyper! En härledd klass är både sin egen datatyp och basklassens datatyp! En vikarie kan alltså användas som Person, Employee och Substitute. Vi bör dock tänka oss för vid tilldelningar! Person p"p", "1"}; Substitute s"s", "2", "3", 0}; p = s; // Ok, men ger slicing Employee& e = s; // Ok Person* pp = &s; // Ok Substitute v = e; // Compilation error!

14 / 33 En härledd klass har flera datatyper! En referens av typ T kan hänvisa till en typ härledd från T. En referens av typ T kan inte hänvisa till en bastyp av T. Ovanstående gäller även pekare! Ett objekt av typ T rymmer aldrig en härledd typ och kan inte lagra enbart en bastyp.

15 / 33 Exempel: std::ostream& std::ostream är basklassen för alla utströmmar! Genom använda en std::ostream& som parameter kan funktioner ta valfri härledd utströmtyp! void print_hello(ostream& os) os << "Hej" << endl; } ofstream ofs"hello.txt"}; ostringstream oss; print_hello(ofs); // print to file print_hello(oss); // print to stringstream print_hello(cout); // print to standard output print_hello(cerr); // print to standard error

16 / 33 Exempel: std::exception& std::exception är basklassen för alla standardundantag! Genom att fånga en basklassreferens kommer vi att fånga även alla undantag härledda från den fångade basklasstypen! try // Kod som kastar undantag... } catch( logic_error& e) // Fångar logic_error i första hand } catch( exception& e ) // Fångar klasser härledda från exception i andra hand }

17 / 33 Löneberäkning för olika kategori anställda Vi kan samla olika kategorier av anställda i en lista! Hur blir det om lönen ska beräknas olika? vector <Employee*> v; v.push_back(new Employee...}); v.push_back(new Programmer...}); v.push_back(new CEO...}); v.push_back(new Consult...}); for ( Employee const* e : v ) cout << e->salary() << endl; }

18 / 33 Programmer class Programmer : public Employee public: Programmer(..., double e = 1.0) : Employee(...), expertisee} } int salary() const return salary * experise; } private: double expertise; };

19 / 33 Consultant class Consultant : public Employee public: Consultant(..., int p, int h) : Employee(...), hour_payp}, hours_workedh} } int salary() const return salary + hour_pay * hours_worked; } private: int hour_pay; int hours_worked; };

20 / 33 CEO class CEO : public Employee public: CEO(..., int bonus = 1000000) Employee(...), bonusbonus} } int bonus() const return bonus; } int salary() const return salary + bonus; } private: int bonus; };

21 / 33 Publikt vs privat arv Har du tänkt på varför public behövs vid arv? class CEO : public Employee Vad händer om vi skriver något annat? public: medlemmar i basklassen behåller deklarerat skydd protected: public medlemmar i basklassen blir protected i härledd klass private: alla medlemmar i basklassen blir private i härledd klass Notera att privata medlemmar i basklassen aldrig är åtkomliga i subklassen. Lämnar du tomt väljs privat arv som standard.

22 / 33 Löneberäkning för olika kategori anställda Om inget annat anges får vi statisk bindning! Det är alltså Employee::salary() som anropas! vector <Employee*> v; v.push_back(new Employee...}); v.push_back(new Programmer...}); v.push_back(new CEO...}); v.push_back(new Consult...}); for ( Employee const* e : v ) cout << e->salary() << endl; }

23 / 33 Dynamisk bindning (virtual, override) Basklassen måste med virtual ange om härledda klasser har en egen variant en funktion! Den härledda klassen ska med override ange att den ersätter basklassens variant! class Employee : public Person... virtual int salary() const;... protected: int salary; }; class CEO : public Employee... int salary() const override;... };

24 / 33 Polymorfi När funktionen är virtual får vi dynamisk bindning (polymorfi)! Nu är det den salary() som finns i det objekt som pekas ut som anropas! vector <Employee*> v; v.push_back(new Employee...}); v.push_back(new Programmer...}); v.push_back(new CEO...}); v.push_back(new Consult...}); for ( Employee const* e : v ) cout << e->salary() << endl; }

25 / 33 Bara pekare och referens kan ha dynamisk typ Vi får endast dynamisk bindning när: Vi från en basklasspekare anropar en virtual funktion, eller Vi från en basklassreferens anropar en virtual funktion!

26 / 33 Dynamisk typomvandling När vi har en basklasspekare eller basklassreferens vill vi ibland ta reda på om den i själva verket hänvisar till en viss härledd klass. for ( Employee const* e : v ) CEO* ceo dynamic_cast <CEO*>(e) }; if ( ceo!= nullptr ) cout << ceo->bonus(); } cout << e->salary() << endl; }

27 / 33 Abstrakt klass (= 0) Vi kan i basklassen säga att det inte finns någon lämplig implementation av en virtual funktion. Då måste varje härledd klass tillhandahålla en egen implementation. Basklassen blir abstrakt. class Employee : public Person... virtual int salary() const = 0;... }; Employee e...}; // Compilation error, incomplete class Employee* e new CEO...}};

28 / 33 Minneshantering med polymorfi Vi måste som vanligt ta bort allt vi skapat med new, men...? vector <Employee*> v; v.push_back(new Employee...}); // Compilation error, incomplete class v.push_back(new Programmer...}); v.push_back(new CEO...}); v.push_back(new Consult...});... for ( Employee const* e : v ) delete e; // Endast destruktorn för Employee! }

29 / 33 Virtuell destruktor Vi behöver göra även destrukton virtual! class Employee : public Person public:... virtual ~Employee() = default;... } for ( Employee const* e : v ) delete e; // Varje destruktor anropas, den mest härledda först! }

30 / 33 Smartpekare - unique_ptr I standardbiblioteket finns speciella klasser för att hålla reda på pekare som en resurs. Klasserna unique_ptr och shared_ptr! vector <unique_ptr <Employee >> v; v.push_back(unique_ptr <Employee >new Employee...}}); // Same as below... v.push_back(make_unique <Employee >(...)); //...but this is safer! v.push_back(make_unique <CEO >(...));... } // Destructor for vector start destructor for stored unique_ptr's!

31 / 33 Egen standardbaserad undantagsklass Vi kan skapa egna typer av undantag genom att ärva från ett standardundantag! noexcept anger att undantag inte slängs. class Stack_Error : public std::logic_error public: using std::logic_error::logic_error; }; class Code_Error : public std::exception public: Code_Error(int code) noexcept : exception}, codecode} } const char* what() const noexcept return ""; } int get_error_code() const return code; } private: int code; };

32 / 33 Överkurs: Interface Ibland vill vi bara bestämma vilka operationer som ska gå att utföra på en viss typ av objekt. Vi bestämmer objektets gränssnitt (interface). I C++ kan vi då skapa en helt abstrakt klass (enbart virtual funktioner): class Stack_Interface public: virtual void push(int value); virtual void pop(); virtual int& top(); virtual int top() const; virtual bool empty() const; }; class Linked_Stack : public Stack_Interface... } class Vector_Stack : public Stack_Interface... } void use_stack(stack_interface& stack); // Pass in any type of stack!

33 / 33 Överkurs: Non virtual interface (NVI) Ibland rekommenderas att virtual funktioner placeras privat. Det gör det enklare att ändra hur klassen löser problem internt utan att ändra på hur den används. class Stack_Interface public: void push(int value); void pop();... private: // The v_ prefix is to avoid clash with public name virtual void v_push(int value); virtual void v_pop();... };

Klas Arvidsson Institutionen för datavetenskap www.liu.se