Tommy Färnqvist, IDA, Linköpings universitet



Relevanta dokument
TDDC76 PoD OH Föreläsning C Härledda klasser

Kommentarer till Person

Skapa, kopiera och destruera klassobjekt

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 {

Introduktion till arv

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

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

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

TDDC76 - Programmering och Datastrukturer

Klasser och objekt i C#

TDDC76 - Programmering och Datastrukturer

Lektionsuppgifter. TDDI14 Objektorienterad programmering. Lektionsplanering Lektion Lektion Lektion

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

Dynamisk bindning och polymorfism

TDDC76 Programmering och datastrukturer

OOP Objekt-orienterad programmering

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

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

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

TDDC76 - Programmering och Datastrukturer

TDIU01 Programmering i C++

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

1. Klass med en dynamiskt allokerad variabel, definitionsfilen-del Klass med en dynamiskt allokerad variabel, inkluderingsfilen.

Övningar Dag 2 En första klass

Föreläsning 5 (6) Metoder. Metoder Deklarera. Metoder. Parametrar Returvärden Överlagring Konstruktorer Statiska metoder tostring() metoden javadoc

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

Introduktion. Den objektorienterade modellen Grundläggande begrepp Klass Klassen som abstraktion

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

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

Objektorientering - Arv och polymorfi

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

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

TDDI14 Objektorienterad programmering

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

Arv. Objektorienterad och komponentbaserad programmering

allokeras på stacken dynamiskt new delete

Minneshantering. Minneshantering. Minneshantering. Undvik pekare

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

Tommy Färnqvist, IDA, Linköpings universitet

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

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

OOP Objekt-orienterad programmering

Föreläsning 2 Objektorienterad programmering DD1332. Typomvandling

5 Arv och dynamisk bindning FIGUR

Programsystemkonstruktion med C++

TENTAMEN. Kurs: Objektorienterad programmeringsmetodik 5DV133 Ansvarig lärare: Anders Broberg. VT-13 Datum: Tid: kl

Tentamen i TDP004 Objektorienterad Programmering Lösningsförslag

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

Objekt och klasser - Introduktion. Objekt. SparKonto.java 2. SparKonto.java 1. Konton.java. Ett objekt har: Ett bankkonto

DD2387 Programsystemkonstruktion med C++ Tentamen 1 Torsdag 7 januari 2016, 14:00-18:00

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

Innehåll. Pekare Exempel

Synlighet. Namespace Scope-operatorn Klasser Vänner

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

Innehåll. Användardefinierade typer. Användardefinierade typer Kategorier. Konstruktorer. Konstruktorer Två sätt att skriva initiering av medlemmar

Objektorienterad programmering D2

Innehåll. Pekare Exempel

Arv bakgrund (kap. 9)

Malmö högskola 2007/2008 Teknik och samhälle

Objektorienterad Programmering (TDDC77)

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

Föreläsnings 10 - Överlagring, Konstruerare, Arv, Mer Exceptions, Reguljära Uttryck

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

Tillämpad programmering

Collections Collections "Envisa" objekt Klasserna Bofstream och Bifstream Definition av metoder i klasserna Bifstream och Bofstream Klassen Streng

Föreläsning 8 Programmeringsteknik och Matlab 2D1312/2D1305. Klass Object, instans av klass public/private Klassvariabler och klassmetoder

C++ Objektorientering - Klasser. Eric Elfving

Kapitel 6 - Undantag

Polymorfi. Objektorienterad och komponentbaserad programmering

Programmering i C++ EDA623 Mer om klasser. EDA623 (Föreläsning 6) HT / 26

DAT043 - Föreläsning 7

Kopiering av objekt i Java

Objekt och klasser - Introduktion

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

F8: Typkonvertering i C++

Mera om generik. Innehåll. Generik och arv Wildcards Vektorer och generik Generiska metoder. EDA690 (Mera om generik) HT / 24

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

Classes och Interfaces, Objects och References, Initialization

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

F8 - Arv. ID1004 Objektorienterad programmering Fredrik Kilander

public och private Obs: private inte skyddar mot access från andra objekt i samma klass.

Grundläggande programmering, STS 1, VT Sven Sandberg. Föreläsning 14

Föreläsning 5: Rekursion

Föreläsning 4. Klass. Klassdeklaration. Klasser Och Objekt

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

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

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

OOP Objekt-orienterad programmering

Tentamen EDAF30 Programmering i C++

Konstruktion av klasser med klasser

Java, klasser, objekt (Skansholm: Kapitel 2)

OOP Objekt-orienterad programmering

Kungliga Tekniska Högskolan Ämneskod 2D4134 Nada Tentamensdag maj - 19 Tentamen i Objektorientering och Java Skrivtid 5 h

Distribuerade system. CORBA eller RMI

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

Idag: Dataabstraktion

Rekursion: varför? Problem delas upp i mindre bitar algoritm för att lösa problemet erhålls från problemformuleringen

1 Klasser och objektorientering Vad är objektorientering?

Transkript:

Föreläsning 11 Arv, polymorfi TDDD86: DALP Utskriftsversion av föreläsning i Datastrukturer, algoritmer och programmeringsparadigm 5 oktober 2015 Tommy Färnqvist, IDA, Linköpings universitet 11.1 Innehåll Innehåll 1 Härledda klasser 1 1.1 Introduktion.......................................... 1 1.2 En polymorf klasshierarki................................... 2 1.3 Dynamisk typkontroll..................................... 7 1.4 Dynamisk typomvandling................................... 8 11.2 1 Härledda klasser 1.1 Introduktion Härledda klasser C++ har en relativt komplett och komplicerad modell för härledning/arv stödjer flera sätt för subklasser att ärva från sina basklasser enkelt arv endast en direkt basklass multipelt arv två eller flera direkta basklasser upprepat arv en indirekt basklass ärvs flera gånger via multipelt arv multipelt och upprepat arv kan leda till tvetydigheter 11.3 Tillgänglighet för basklassmedlemmar Flera sätt att specificera tillgänglighet för basklassmedlemmar i den härledda klassen public basklass public-medlemmarna i basklassen blir public i den härledda klassen (protected blir protected) protected basklass public-medlemmarna i basklassen blir protected i den härledda klassen (protected blir protected) private basklass public-medlemmarna i basklassen blir private i den härledda klassen (protected blir private) en klass kan utse vänner en friend har åtkomst till alla medlemmar, även privata 11.4 Polymorft beteende Polymorft beteende bestäms av programmeraren objekt som ska bete sig polymorft måste refereras via pekare eller referenser endast anrop av virtuella medlemsfunktioner kan bindas dynamiskt och därmed uppvisa polymorft beteende 11.5 1

1.2 En polymorf klasshierarki Person-Employee-Manager-Consultant en polymorf klasshierarki Person personer i allmänhet har namn och personnummer alla anställda ska dela egenskaperna hos denna klass inga objekt ska kunna skapas ska vara en abstrakt klass Employee anställda i allmänhet har anställningsdatum, anställningsnummer, lön, anställning vid en avdelning mer specialiserade kategorier av anställda ska härledas från denna klass objekt ska kunna skapas Manager anställda som är avdelningschefer ansvarar för en avdelning och dess anställda Consultant (tillfälligt) anställda som är konsulter ingen direkt skillnad jämfört med en anställd i allmänhet, men ska gå att skilja ut typmässigt 11.6 Person class Person public: virtual ~Person() = default; virtual std::string str() const; virtual Person* clone() const = 0; std::string get_name() const; void set_name(const std::string&); CRN get_crn() const; void set_crn(const CRN&); protected: Person(const std::string& name, const CRN& crn); Person(const Person&) = default; private: Person& operator=(const Person&) = delete; ; std::string name_; CRN crn_; 11.7 Konstruktor som tar namn och personnummer Person::Person(const std::string& name, const CRN& crn) : name_ name, crn_ crn Säkerställer att en ny Person alltid har ett namn och ett personnummer 2

defaultkonstruktorn genereras e ingen annan konstruktor är tillgänglig som kan initiera objekt på något annat sätt, utom kopieringskonstruktorn och flyttkonstruktorn ska endast användas av motsvarande konstruktor i subklasserna protected 11.8 Medlemsfunktionen str() virtual std::string str() const; Definition: string Person::str() const return name_ + + crn_.str(); Anrop kommer att bindas dynamiskt, om objektet refereras av pekare eller referens. den dynamiska typen avgör vilken överskuggning som anropas Person* p new Managername, crn, date, employment_number, salary, dept ; cout << p->str() << endl; pekaren p har statisk typ Person* uttrycket *p har dynamisk typ Manager (*p).str() Manager::str() anropas föredra piloperatorn i detta fall p->str() Medlemsfunktionen clone() virtual Person* clone() const = 0; Polymorfa klasser behöver ibland en polymorf kopieringsfunktion. använder man polymorfa klasser innebär det ibland att man ska allokera objekten dynamiskt och hanterar dem via pekare kräver en polymorf kopieringsfunktion som clone() varje konkret subklass måste ha sin egen specifika överskuggning av clone() strömklasserna i STL är exempel på polymorfa klasser som e ska kunna kopieras saknar publik kopieringskonstruktor 11.9 11.10 Subklassen Employee class Employee : public Person public: Employee(const std::string& name, const CRN& crn, const Date& e_date, e_number, double salary, dept = 0); ~Employee() = default; std::string str() const override; Employee* clone() const override; //returtypen kovariant med Person* get_department() const; Date get_employment_date() const; get_employment_number() const; double get_salary() const; protected: Employee(const Employee&) = default; 11.11 3

Subklassen Employee (forts.) private: Employee& operator=(const Employee&) = delete; friend class Manager; void set_department( dept); void set_salary(double salary); ; Date double e_date_; e_number_; salary_; dept_; 11.12 Publik konstruktor för Employee Employee::Employee(const string& name, const CRN& crn, const Date& e_date, e_nbr, double salary, dept) : Personname, crn, e_date_e_date, e_number_e_nbr, salary_salary, dept_dept Person-subobjektet initieras per definition först Person-initieraren ska finnas först i initierarlistan anrop av motsvarande konstruktor i Person Employees egna datamedlemmar initieras sedan i deklarationsordning skriv deras initierare i samma ordning en konstruktor ska uttryckligen initieras alla basklasser och icke-statiska datamedlemmar 11.13 Medlemsfunktionen str() överskuggas string Employee::str() const return Person::str() + " (Employee) " + e_date_.str() + + std::to_string(dept_); anropar str() för Person-subobjektet för att generera en del av strängen som ska returneras kvalificerat namn Person::str() krävs för att undvika rekursion 11.14 Medlemsfunktionen clone() överskuggas Employee* clone() const return new Employee *this ; ska skapa en kopia av det objekt som anropar clone() och returnera en pekare till kopian kopieringskonstruktorn är den naturliga operationen för att göra kopian anropar i sin tur kopieringskonstruktorn för Person när returtypen tillhör en polymorf klasshierarki kan vi anpassa returtypen Employee* p1 new Employee name, crn, date, employment_nbr, salary ; Employee* p2 = p1->clone(); // ingen typomvandling om // clone() returnerar Employee* Person* p3 = p1->clone(); // implicit typomvandling till Person* - upcast typerna sägs vara kovarianta 11.15 4

Subklassen Manager class Manager : public Employee public: Manager(const std::string& name, const CRN& crn, const Date& e_date, e_number, double salary, dept); ~Manager() = default; std::string str() const override; Manager* clone() const override; void add_department_member(employee* ep) const; void remove_department_member( e_number) const; void pr_department_list(std::ostream&) const; void raise_salary(double percent) const; protected: Manager(const Manager&) = default; private: Manager& operator=(const Manager&) = delete; ; // Manager äger e Employee-objekten, destruering // av dessa ska e utföras av Manager mutable std::map<, Employee*> dept_members_; 11.16 Publik konstruktor för Manager Manager(const std::string& name, const CRN& crn, const Date& e_date, e_number, double salary, dept) : Employee name, crn, e_date, e_number, salary, dept alla parametrar överförs som argument till den direkta basklassen Employee dept_members har defaultkonstruktion en tom lista med anställda skapas 11.17 Medlemsfunktionenerna str() och clone() överskuggas string Manager::str() const return Person::str() + " (Manager) " + get_employment_date().str() + + std::to_string(get_department()); Manager* clone() const return new Manager *this ; Antag att vi skulle ha glömt att överskugga clone() för Manager: den sista överskuggaren (last override) vore då Employee::clone() i stället för en Manager skulle clone() returnera en Employee kopia av Employee-subobjektet i den Manager som skulle ha kopierats 11.18 Anställda på avdelningen hanteras av Manager void Manager::add_department_member(Employee* ep) const // Avdelningen för den anställda ska vara samma som avdelningschefens ep->set_department(get_department()); // vänskap behövs // Lägg till i avdelningens lista över anställda dept_members_.insert(make_pair(ep->get_employment_number(), ep)); 5

Manager måste vara friend till Employee för att få anropa private-medlemmen set_department i denna kontext parametern ep är en pekare till Employee endast public-operationer är tillåtna via ep, om e Manager är vän till Employee om ep varit pekare till Manager hade e friend behövts En medlemsfunktion i Manager kan komma åt private-medlemmar i sig själv och i andra Manager-objekt kan komma åt protected-medlemmar, egna och ärvda, i sig själv och andra Manager-objekt kan bara komma åt public-medlemmar i objekt av typ Employee och Consultant, om e friend 11.19 Subklassen Consultant class Consultant final : public Employee // ingen subklassning tillåten public: using Employee::Employee; // konstruktorer ärvs ~Consultant() = default; std::string str() const override; Consultant* clone() const override; protected: Consultant(const Consultant&) = default; private: Consultant& operator=(const Consultant&) = delete; ; 11.20 Initiering och destruering av objekt av härledd typ ett objekt av härledd typ består av delar, subobjekt subobjekt som motsvarar klassens basklasser klassens egna datamedlemmar initieringsordningen är uppifrån-och-ner basklassens datamedlemmar initieras före subklassens första konstruktorn som anropas är konstruktorn för den mest härledda klassen destrueringsordningen är omvänd mot initieringsordningen nerifrån-och-upp datamedlemmarna i en subklass destrueras före datamedlemmarna i en basklass först anropas den mest härledda klassens destruktor datamedlemmarna i klassen destrueras i omvänd deklarationsordning viktigt att rotklassen i polymorf klasshierarki har virtuell destruktor Person* p new Consultant(...) ;... delete p; // ~Person() eller ~Consultant()? 6

11.21 Använda Person, Employee, Manager, Consultant Person* pp nullptr ; // kan peka på Employee-, Manager- eller // Consultant-objekt (Person är abstrakt) Employee* pe nullptr ; // kan peka på Employee-, Manager- eller // Consultant-objekt Manager* pm nullptr ; // kan endast peka på ett Manager-objekt Consultant* pc nullptr ; // kan endast peka på ett Consultant-objekt pm = new Manager name, crn, date, employment_nbr, salary, 17 ; pp = pm; // upcast sker automatiskt // Manager* -> Person* pm = dynamic_cast<manager*>(pp); // downcast måste göras uttryckligen // Person* -> Manager* if (pm!= nullptr) // har vi en Manager? pm->pr_department_list(cout); polymorfa pekare kan peka på objekt som motsvarar pekarens typ och subtyper upcast är en automatisk och säker typomvandling downcast måste göras uttryckligen och kan behöva kontrolleras innan vi opererar på objektet pr_department_list() är specifik för Manager och kan bara anropas via pekare av typ Manager* 11.22 1.3 Dynamisk typkontroll Dynamisk typkontroll Ett sätt att ta reda på ett objekts typ är med typeid-uttryck inkludera <typeinfo> if (typeid(*pp) == typeid(manager))... kan användas för typnamn, objekt och all slags uttryck ett typeid-uttryck returnerar ett objekt av typen type_info typkontroll kan göras genom att jämföra två type_info-objekt 11.23 typeid-uttryck typeid-uttryck: typeid(*p) returnerar ett type_info-objekt för den typ av objekt som pekaren p pekar på typeid(r) returnerar ett type_info-objekt för den typ av objekt som referensen r refererar till typeid(t) returnerar ett type_info-objekt för typen T typeid(p) är vanligtvis ett misstag om p är en pekare ger type_info-objekt för pekartypen type_info-operationer: == testar likhet mellan två type_info-objekt!= testar olikhet mellan två type_info-objekt name() returnerar typens namn i form av en C-sträng 11.24 7

Dynamisk typkontroll (forts.) Typkontroll kan även göras med dynamic_cast användning för polymorf pekare Manager* pm dynamic_cast<manager*>(pp) ; // typomvandla pp if (pm!= nullptr) pm->pr_department_list(cout); dynamic_cast returnerar nullptr om pp e pekar på ett objekt av typen Manager eller en subtyp till Manager användning för polymorf referens rp antas ha typ Person& dynamic_cast<manager&>(rp).pr_department_list(cout); om e rp anger ett objekt av typen Manager, eller en subtyp till Manager, kastas undantaget bad_cast det finns inget tomma-referensen-värde en referens måste alltid vara bunden till ett objekt 11.25 1.4 Dynamisk typomvandling Dynamisk typomvandling Med operatorn dynamic_cast kan man typomvandla polymorfa pekare och referenser: dynamic_cast<t*>(p) omvandlar pekaren p till pekare till T dynamic_cast<t&>(r) omvandlar referensen r till referens till T downcast från bastypspekare till subtypspekare eller från bastypsreferens till subtypsreferens upcast är en automatisk och säker typomvandling vid multipelt arv förekommer även crosscast 11.26 8