Videregående Programmering for Diplom-E Noter



Relaterede dokumenter
Abstrakte datatyper C#-version

Objektorientering. Programkvalitet

Programmering i C. Lektion december 2008

SWC eksamens-spørgsmål. Oversigt

AAU, Programmering i Java Intern skriftlig prøve 18. maj 2007

METODER ARV KLASSER. Grundlæggende programmering Lektion 5

18 Multivejstræer og B-træer.

Ugeseddel 4 1. marts - 8. marts

DM507 Algoritmer og datastrukturer

Objektorienteret design med arv og polymorfi:

DM507 Algoritmer og datastrukturer

Rename og redefine. Abstrakte klasser. Dynamisk binding.

Skriftlig eksamen i Datalogi

JavaScript. nedarvning.

19 Hashtabeller. Noter. PS1 -- Hashtabeller. Hashing problemet. Hashfunktioner. Kollision. Søgning og indsættelse.

Software Construction 1 semester (SWC) Spørgsmål 1

Videregående Programmering Obligatorisk opgave - 3. semester, efterår 2004

KAPITEL 8: OPRETTELSE OG ADMINISTRATION AF DOKUMENTGODKENDELSE

DM507 Algoritmer og datastrukturer

Eksamensopgaver datalogi, dlc 2011 side 1/5. 1. Lodtrækningssystem

Eksamensadministration, EUD, udtrækning af elever Sidst opdateret /version 1.3 /UNI C/Steen Eske Christensen

Individ og fællesskab

C++ Programmering V

CCS Formål Produktblad December 2015

Skriftlig eksamen i Datalogi

dcomnet-nr. 6 Talrepræsentation Computere og Netværk (dcomnet)

REGLER FOR DANMARKSRANGLISTEN FOR SENIORER

Klasser og Objekter i Python. Uge 46 Learning Python: kap 15-16,

Kursus navn: Indledende programmering Kursus nr

Udvidelse og specialisering. Klassehierarkier. Nedarvningsterminologi. Interfaces. Statiske og dynamiske typer. Polymorfi. Abstrakte klasser.

Specifikation Abstrakt OO OS-API Rev Specifikation. Abstrakt, objektorienteret operativsystem-api

DM507 Algoritmer og datastrukturer

Att: Mads Ellehammer:

Singleton pattern i Java

Uniq.Survey-Xact.DK. Vejledning. Rambøll Management Olof Palmes Allé 20 DK-8200 Århus N Denmark. Tlf:

DM507 Algoritmer og datastrukturer

Hvad er Objekter - Programmering

Klasser og nedarvning

Tree klassen fra sidste forelæsning

Athena DIMENSION Varmeanlæg 4

Faggruppernes troværdighed

Tips og vejledning vedrørende den tredelte prøve i AT, Nakskov Gymnasium og HF

Anvendelse af metoder - Programmering

Rapport vedrørende. etniske minoriteter i Vestre Fængsel. Januar 2007

Indledning... 2 Opbygning... 2 Servicesegmenternes sammenhæng... 3 UNA... 4 UNB... 6 UNH UNT UNZ... 14

Modelbase findes under Maskinhandel Opsætning Modelbase.

Forslag til oprettelse af et konferencemodul

Når arbejdsulykken er sket Vejledning til arbejdsmiljøgruppen

HVORDAN KAN REFERENCEARKITEKTUR IMPLEMENTERES I EN STANDARDISERET DOKUMENTATION?

Kursusarbejde 3 Grundlæggende Programmering

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { int wmid, wmevent; programmering med

Side 1 af 16. Vedligehold decentrale stamdata i SKS

GLAMSBJERG FRI- OG EFTERSKOLE

Pædagogiske læreplaner

Metoder Klasser Arv. Operatorer Løkker. Praksis eksempel. Grundlæggende programmering Lektion 3

Forslag til visioner og strategier for fremtidens overbygning i Norddjurs Kommune

Objektorienteret Programmering

Kursus i OOP og Java. Kursus i Objektorienteret programmering i Java

3 Algebraisk Specifikation af Abstrakte Datatyper.

Java Programmering. En bog for begyndere. Skrevet af Henrik Kressner

Hvad sker der med sin i moderne dansk og hvorfor sker det? Af Torben Juel Jensen

GPS-Link version Brugervejledning Dansk Sejlunion

Få navn på analysenr. i excel-fil og ind i pivottabel med data fra qlikview

Notat. Introdansk beskrivelse af fastlagte krav til indberetning af statistikoplysninger fra udbydere JL

Indholdsfortegnelse Avanceret søgning:

Allan C. Malmberg. Terningkast

3.0 Velkommen til manualen for kanalen Shift Introduktion til kanalen Hvad er et spot? Opret et nyt spot 2

Eksempler på elevbesvarelser af gådedelen:

0KAPITEL 5: DOKUMENTGODKENDELSE OPSÆTNINGSVEJLEDNING

Transkript:

Videregående Programmering for Diplom-E Noter 1. Uddelegering Ét af de væsentlige principper i objektorienteret programmering er, at enhver klasse selv skal kunne "klare ærterne". Enhver klasse skal altså have metoder til alle typiske opgaver. Et eksempel på dette er funktionen 'vis', der udskriver værdien af attributterne på skærmen. I bil/person/elev-eksemplet ser dette sådan ud: bil person vis vis elev vis Klassen 'bil', 'person' og 'elev' har hver sin vis-funktion. Men for at kunne virke, må disse visfunktioner "samarbejde". F.eks. må vis-funktionen i klassen 'person' overlade en del af sit arbejde til vis-funktionen i klassen 'bil' - nemlig den del der går ud på at vise oplysninger om personens bil. Det samme kan siges om vis-funktionen i klassen 'elev'. Man kalder denne form for samarbejde for uddelegering (eng.: propagation). Uddelegering i denne forstand er karakteristisk for objektorienterede programmer. ehovet for uddelegering kommer af, at attributterne i en klasse jo normalt er specificeret private - de kan defor kun tilgås gennem metoder. I det følgende ser vi nærmere på, hvordan uddelegering rent teknisk foregår for køber/sælgerrelationens og arve-relationens vedkommende. 1.1 Uddelegering i køber/sælger-relationen Realiseringen i C++ af den ovenfor viste køber/sælger-relation mellem klasserne 'person' og 'bil' ser sådan ud: class bil class person 1

//data //data private: private: bil denne_persons_bil; //metoder //metoder void vis(); void vis(); ; ; Køber/sælger-relationen mellem 'person' og 'bil' er altså realiseret ved at 'person' indeholder et attribut af typen 'bil' - d.v.s. et objekt af typen bil. Dette objekt ved navn 'denne_persons_bil' udgør sammenhængen mellem de 2 klasser. En skabelon for vis-funktionen i klassen 'person' ser sådan ud: void person::vis() denne_persons-bil.vis(); //udskriften af attributten //'denne_persons_bil' uddelegeres til bil- //klassens egen vis-funktion cout<< //udskrift af de øvrige attributter Den indbyrdes rækkefølge mellem disse 2 dele af funktionen kan naturligvis vælges anderledes. Uddelegeringen foregår altså gennem det eller de involverede objekt(er) - i dette tilfælde 'denne_persons_bil'. Generelt kan man formulere dette princip på flg. måde: 's vis-funktion uddelegerer til 's vis-funktion vis _objekt vis uddelegering: _objekt.vis() 2

1.2 Uddelegering i arve-relationen Realiseringen i C++ af den ovenfor viste arve-relation mellem klasserne 'person' og 'elev' ser sådan ud: class person class elev: public person //data //data private: private: bil denne_persons_bil; //metoder //metoder void vis(); void vis(); ; ; rve-relationen mellem 'elev' og 'person' er altså realiseret ved at 'elev' direkte specificerer arven i sin definition. En skabelon for vis-funktionen i klassen 'elev' ser sådan ud: void elev::vis() person::vis(); //udskriften af den del af objektet, der er //arvet fra klassen 'person' uddelegeres til //vis-funktionen i klassen 'person' cout<< //udskrift af de øvrige attributter Den indbyrdes rækkefølge mellem disse 2 dele af funktionen kan naturligvis vælges anderledes. Da et objekt af klassen 'elev' direkte indeholder de arvede attributter og metoder fra klassen 'person', skal vis-funktionen i klassen 'person' her ikke kaldes "gennem" et objekt - det hele foregår jo indenfor ét og samme objekt. I stedet er vi nødt til at angive den uddelegerede vis-funktions scope: person::vis(). Ellers ville systemet opfatte det som om funktionen "kaldte sig selv". Generelt kan man formulere dette princip på flg. måde: 3

C's vis-funktion uddelegerer til 's vis-funktion vis uddelegering: ::vis() C vis Løsningsforslaget i afsnit 3.4 til opgave 4.5.3 viser et eksempel på uddelegering både i køber/sælger-relationen og i arve-relationen. 2. utomatisk uddelegering mellem constructorer En constructor er en metode, der tjener til at initialisere objekter. ehovet for uddelegering er derfor nøjagtigt det samme for constructorer som for andre metoders vedkommende. Som bekendt kaldes constructorer automatisk ved oprettelsen af objekter. Derfor foretages uddelegeringen også automatisk når det er constructorer, det drejer sig om. Dette foregår således: 2.1 køber/sælger-relationen 's constructor uddelegerer automatisk til 's constructor constructor _objekt constructor Et objekt indeholder af klassen indeholder iflg. 's definition et objekt af klassen ("_objekt"): 4

() () objekt_ objekt af klassen Når et objekt af klassen oprettes, kaldes automatisk 's constructor. Denne constructor sætter objektet op med de værdier, der er specificeret i constructoren. En del af dette arbejde går ud på at sætte det indeholdte objekt ('objekt_') op - denne del af arbejdet uddelegeres automatisk til 's constructor. Hvis klassen 's constructor har en parameterliste, skal værdier svarende til denne parameterliste "stilles til rådighed" for det automatiske kald. Til dette benyttes en initialiseringsliste i 's constructor: class class objekt_; (int i, char c); (int i, char c); ; ; ::(int i, char c):objekt_(i,c) Med fede typer er vist constructoren 's initialiseringsliste - i dette tilfælde navnet på det objekt, der skal initialiseres (objekt_) og en parameterliste med de værdier, dets constructor skal have som aktuelle parametre (i og c). Denne initialiseringsliste bevirker, at inden 's constructor udføres, så vil automatisk 's constructor udføres på det anførte objekt med de anførte værdier. I det viste eksempel er -constructorens parameterværdier hentet ind som parametre i - constructoren. -constructoren sender på den måde blot sine modtagne parameterværdier videre til -constructoren. -constructoren kan naturligvis herudover have parametre "til eget brug". 5

-constructorens aktuelle parametre i initialiseringslisten behøver ikke nødvendigvis komme fra -constructorens parametre selvom dette vil være det normale. 2.2 arve-relationen C's constructor uddelegerer automatisk til 's constructor constructor C constructor P.g.a. arven fra indeholder et objekt af klassen C både en del, der svarer til 's definition og en del, der svarer til C's egen definition: (C) indhold svarende til 's definition indhold svarende til C's definition objekt af klassen C Når et objekt af klassen C oprettes, kaldes automatisk C's constructor. Denne starter med automatisk at uddelegere opsætningen af 's del af objektet til 's constructor. Herefter sætter den selv resten af objektet op, d.v.s. den del der svarer til C's egen definition. Hvis klassen 's constructor har en parameterliste, skal værdier svarende til denne parameterliste "stilles til rådighed" for det automatiske kald. Til dette benyttes en initialiseringsliste i C's constructor: 6

class class C (int i, char c); C(int i, char c); ; ; C::C(int i, char c):(i,c) Med fede typer er vist constructoren 's initialiseringsliste - i dette tilfælde navnet på den klasse, der arves fra og en parameterliste med de værdier, dens constructor skal have som aktuelle parametre (i og c). Denne initialiseringsliste bevirker at inden C's constructor udføres, så vil 's constructor automatisk blive udført således at 's del af objektet sættes op med de anførte værdier. I det viste eksempel er -constructorens parameterværdier hentet ind som parametre i C- constructoren. C-constructoren sender på den måde blot sine modtagne parameterværdier videre til -constructoren. C-constructoren kan naturligvis herudover have parametre "til eget brug", d.v.s. til den del af objektet der ikke er arvet. 3. cceskontrol ved arv Ved nedarvning kan specificeres en kollektiv acceskontrol på 3 måder: OMT: private protected public C++: 7

class : private class : protected class : public eller blot: class : Denne form for acceskontrol påvirker ikke den klasse, der specificerer den, men dens omgivelser (d.v.s. dens klienter og afledte klasser ). Klassen ovenfor påvirkes altså ikke af den anførte acceskontrol. Den acceskontrol, en klasse specificerer ved arv, påvirker muligheden for "udefra" at referere til det, klassen har arvet. I eksemplet ovenfor drejer det sig m.a.o. om omgivelsernes muligheder for "gennem" klassen at referere til klassen 's attributter og metoder. Her gælder den regel, at en klasses egne interne specifikationer af acceskontrol for attributter og metoder aldrig kan svækkes gennem specifikationen af den kollektive acceskontrol ved arv. 3.1 private arv Hverken klienter eller afledte klasser til den specificerende klasse kan referere til klassemedlemmer i dennes baseklasse: private D her kan ikke refereres til C her kan ikke refereres til private arv er default. Hvis man ikke eksplicit specificerer acceskontrollen ved arv, er der altså tale om private arv. 3.2 protected arv 8

fledte klasser til den specificerende klasse kan referere til klassemedlemmer i dennes baseklasse i overensstemmelse med baseklassens interne acceskontrol-specifikationer. Klienter til den specificerende klasse kan ikke referere til klassemedlemmer i baseklassen: protected D her kan ikke refereres til C her kan refereres til (public og protected medlemmer) Muligheden for at tilgå 's klassemedlemmer "gennem" gælder ikke kun klassen C, men hele klassehierarkiet under - sålænge der ikke arves private. 3.3 public arv åde klienter og afledte klasser til den specificerende klasse kan referere til klassemedlemmer i dennes baseklasse i overensstemmelse med baseklassens interne acceskontrol-specifikationer. 9

public D her kan refereres til (public medlemmer) C her kan refereres til (public og protected medlemmer) 4. Virtuel baseklasse Multipel arv medfører repeteret arv, hvis de multiple baseklasser igen arver fra en fælles baseklasse: i C D ::i C::i (D) 10

Repeteret arv betyder, at en klasse arver ét og samme klassemedlem ad flere veje samtidigt, som det f.eks. er tilfældet med attributten i i klassen D ovenfor. Et objekt af klassen D vil derfor have 2 forekomster af i, hvilket medfører at flg. er ulovligt: D obj_d; obj_d.i = 0; //flertydigt, da 2 attributter hedder 'i' Som regel er repeteret arv uønsket, og man kan undgå det ved at specificere baseklasserne virtual ved multipel arv: class D: virtual public, virtual public C Dette har den effekt, at klassemedlemmer fra fælles baseklasser, der arves ad flere veje, ikke dubleres når der oprettes objekter. 5. friend-specifikationen ved arv Med friend-specifikationen kan en klasse undtage én eller flere klasser og/eller funktioner fra de specificerede acceskontroller i klassen: friend class klassen kan tilgå alle 's klassemedlemmer, uanset acceskontrol En friend-status kan ikke arves: friend class C 's friend-status arves ikke 11

Klassen C er i eksemplet herover underlagt de accekontroller, der internt er specificeret.i klassen. Omvendt arves selve friend-specifikationen: friend class C klassen kan tilgå den del af C's klassemedlemmer, der arves fra, uanset acceskontrollen i Enhver friend-specifikation betragtes altså som knyttet til den specificerende klasse. Den arvede friend-specifikationen giver derfor kun rettigheder m.h.t. baseklassen - ikke m.h.t. den afledte klasse. 6. Typeskabeloner (templates) En abstrakt datatype kendes på dens metoder (mulige operationer) - den tillader/kræver m.a.o. en abstrahering fra datas implementering. Ofte er det naturligt også at kunne abstrahere fra datas type. Det gælder f.eks. når den abstrakte datatype er en datastruktur beregnet på lagring af dataelementer. En stak f.eks. virker på samme måde uanset om dens elementer er af den ene eller anden type. Den logiske konsekvens af begrebet abstrakt datatype er m.a.o. muligheden for en vis frigørelse fra den stærke typebinding, der ellers har kendetegnet de fleste højniveau-programmeringssprog i mange år. C++ tilbyder 2 muligheder for en frigørelse fra den traditionelle typebinding: typeskabeloner (templates) Typer kan parameteroverføres til en datastruktur. Én og samme definition af datastrukturen kan derfor bruges til at oprette f.eks. en datastruktur af heltal og en datastruktur af strenge. 12

polymorfi Objekter indenfor samme arvehierarki kan uanset deres type (klasse) refereres med en pointer til arvehierarkiets baseklasse. Man kan derfor gemme objekter af alle typerne i arvehierarkiet i samme datastruktur. Forskellen mellem typeskabeloner og polymorfi er, at typeskabeloner binder alle elementer i en datastruktur til at være af samme type - det gør polymorfi ikke. Til gengæld sætter typeskabeloner ingen grænser for hvilke typer, der kan vælges - det gør polymorfi, da kun klasser indenfor det pågældende arvehierarki kan vælges. I det følgende skal vi se nærmere på, hvordan man arbejder med typeskabeloner (templates) i C++. Som eksempel benytter vi en klasse stak, hvor stakelementerne ikke er bundet til en bestemt type i definitionen. 6.1 Definition af klasser Når man definerer en klasse, hvori der indgår en ikke fastlagt type (parameteriseret type), skal denne erklæres i klassens hovede på flg. måde: template <class T> class ; etydningen af denne definition er, at 'T' defineres som en typeparameter, der kan bruges inde i definitionen af klassen. Dette betyder, at 'T' inde i klassen kan benyttes som synonym for en type. Definitionen af 'T' som typeparameter er lokal for klassen. Definitionen af en stakklasse kan foregå sådan: template <class T> class stak //definition af en klasse "stak", hvor T //er typeparameter T data[size]; //definition af en tabel "data" med "size" //elementer af typen T int staktop; //index til staktop-elementet stak(); void push(t i); T pop(); //konstruktør, sætter staktop til -1 svarende //til tom stak //lægger værdien 'i' på stakken ("pusher i") //tager øverste element af stakken og returnerer //dets værdi ("popper stakken") 13

; void vis(); //viser hele stakken på skærmen Navnet på typeparameteren kan være enhver lovlig identifikator. Iflg. dokumentationen af C++ kan defineres flere typeparametre samtidigt, men dette fungerer ikke stabilt - sandsynligvis p.g.a. en fejl i compileren. 6.2 Definition af metoder Når en metode fra en klasse med typeparameter defineres udenfor sin klasse, skal typeparameteren igen defineres. Hvis klassen fra før har en metode med prototype void F(); ser definitionen sådan ud: template <class S> void <S>::F() Dette skal forstås således: <S> dette er den måde klassen 's scope betegnes på fordi der indgår en typepartameter nødvendig template <class S> dette er en erklæring af typeparameteren S - fordi typeparameteren indgår i klassens scope For at illustrere at erklæringen af en typeparameter er lokal for den umiddelbart efterfølgende programdel (f.eks. en klasse eller en funktion), er her valgt navnet S. Definitionen af metoderne i klassen 'stak' kan ske således: template <class T> stak<t>::stak() staktop=-1; template <class T> void stak<t>::push(t i) data[++staktop]=i; 14

template <class T> T stak<t>::pop() return data[staktop--]; template <class T> void stak<t>::vis() cout<<endl<<"stakkens indhold: "; for (int i=0; i<=staktop; i++) cout<<data[i]<<" "; 6.3 Oprettelse af objekter Ved oprettelsen af objekter skal angives en type svarende til typeparameteren. Dette sker således: <int> objekt_; Her oprettes objektet 'objekt_' af klassen, og typeparameteren bindes for dette objekts vedkommende til typen int. Et hovedprogram, der bruger klassen 'stak', kan se således ud: void main() stak<int> heltalsstak; stak<char> tegnstak; stak<string> strengstak; //opret en stak, hvor elementværdierne er heltal //opret en stak, hvor elementværdierne er tegn //opret en stak, hvor elementværdierne er strenge heltalsstak.push(2); heltalsstak.push(4); heltalsstak.vis(); tegnstak.push('a'); cout<<endl<<heltalsstak.pop(); strengstak.push("c"); strengstak.push("defg"); tegnstak.pop(); tegnstak.vis(); strengstak.vis(); 15

6.4 Operationer på attributter defineret med typeparametre Når attributter defineres med typeparametre, sætter dette en grænse for hvilke operationer, man kan foretage på disse attributter. Man kan jo ikke foretage operationer, der kun er defineret for bestemte typer. I praksis kan man foretage flg. operationer: - tildeling - parameteroverførsel - i/o med << og >>, forudsat disse operationer er defineret for den parameteroverførte type Især skal man bemærke, at man ikke kan foretage sammenligninger med operatorerne == og!= selvom disse operationer synes logisk veldefineret uanset typen. 16