1 Funktioner och procedurell abstraktion



Relevanta dokument
1 Texthantering. 1.1 Typen char. Exempel, skriv ut alfabetet

Programmeringsteknik med C och Matlab

TDIU01 - Programmering i C++, grundkurs

Programmering i C++ En manual för kursen Datavetenskaplig introduktionskurs 5p

Dagens föreläsning. Repetition. Repetition - Programmering i C. Repetition - Vad C består av. Repetition Ett första C-program

Tentamen OOP

Att använda pekare i. C-kod

TDIU01 - Programmering i C++, grundkurs

1 Datorn som miniräknare. 1.1 Räkneoperationer. 1.2 Variabler

Föreläsning 3.1: Datastrukturer, en översikt

Introduktion till arv

Dagens föreläsning. Repetition. Repetition - Programmering i C. Repetition - Vad C består av. Repetition Ett första C-program

Föreläsning 2 Objektorienterad programmering DD1332. Typomvandling

Övningar Dag 2 En första klass

Programmering A. Johan Eliasson

Vem är vem på kursen. Objektorienterad programvaruutveckling GU (DIT011) Kursbok Cay Horstmann: Big Java 3rd edition.

C++ Funktioner 1. int summa( int a, int b) //funktionshuvud { return a+b; //funktionskropp } Värmdö Gymnasium Programmering B ++ Datainstitutionen

Föreläsning 6: Introduktion av listor

För att skriva data till skärmen ( konsolen) används objektet System.out tillsammans med metoden println eller print.

Programmera i C Varför programmera i C när det finns språk som Simula och Pascal??

Datatyper och kontrollstrukturer. Skansholm: Kapitel 2) De åtta primitiva typerna. Typ Innehåll Defaultvärde Storlek

SMD 134 Objektorienterad programmering

Grundläggande programmering med C# 7,5 högskolepoäng

Objektorienterad programmering i Java

Föreläsning 5-6 Innehåll. Exempel på program med objekt. Exempel: kvadratobjekt. Objekt. Skapa och använda objekt Skriva egna klasser

Föreläsning 5-6 Innehåll

Föreläsning 4: Poster

Inledande programmering med C# (1DV402) 27+15=42 1 (22)

5 Grundläggande in- och utmatning

Variabler och konstanter

Funktionens deklaration

Klassdeklaration. Metoddeklaration. Parameteröverföring

Objektorienterad programmering D2

Föreläsning 1 & 2 INTRODUKTION

732G Linköpings universitet 732G11. Johan Jernlås. Översikt. Repetition. Felsökning. Datatyper. Referenstyper. Metoder / funktioner

Programmering med Java. Grunderna. Programspråket Java. Programmering med Java. Källkodsexempel. Java API-exempel In- och utmatning.

PROGRAMMERING 2 GRUNDLÄGGANDE SEMANTIK 4

Björn Abelli Programmeringens grunder med exempel i C#

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

Java, klasser, objekt (Skansholm: Kapitel 2)

Pascal... Pascal. Pascal... Pascal...

Lite om felhantering och Exceptions Mer om variabler och parametrar Fält (eng array) och klassen ArrayList.

En villkorssats är den konstruktion som finns i C++ för att göra en selektion av två alternativa sekvenser. Formen för if satsen är

Pascal. reserverade ord fördefinierade funktioner och procedurer egendefinierade funktioner, procedurer och objekt

float Mindre rella tal ( floating point number ) double Rella tal/flyttal ( double precision floating point number )

Parameteröverföring. Exempel. Exempel. Metodkropp

Programmering, grundkurs, 8.0 hp, Elektro, KTH, hösten 2010

EDAA20 Programmering och databaser. Mål komprimerat se kursplanen för detaljer. Checklista. Föreläsning 1-2 Innehåll. Programmering.

Introduktionslaboration

1 Egna klasser. 1.1 En punkt-klass

Objektorienterad Programmering (TDDC77)

Algoritmanalys. Genomsnittligen behövs n/2 jämförelser vilket är proportionellt mot n, vi säger att vi har en O(n) algoritm.

Chapter 3: Using Classes and Objects

2D1339 Programkonstruktion för F1, ht 2003

I Skapa Hej.java och skriv programmet. I Kompilera med javac Hej.java. I Rätta fel och repetera tills du lyckas kompilera ditt program

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

Instuderingsfrågor till Steg 1

4 Sammansatta datatyper

Enkla datatyper minne

Föreläsning 6 pekare och pekare tillsammans med arrayer

Grunderna i stegkodsprogrammering

*Pekarvärden *Pekarvariabler & *

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

LÖSNINGSFÖRSLAG TILL Tentamen i objektorienterad programmering i C++ I

Tentamen i. för D1 m fl, även distanskursen. fredag 13 januari 2012

(Man brukar säga att) Java är... Denna föreläsning. Kompilering av Java. Historik: Java. enkelt. baserat på C/C++ Allmänt om Java

Nedan skapar vi klassen Person innehållande datamedlemmar för förnamn, efternamn, ålder, längd och vikt:

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

Datorlära 3 Octave Workspace ovh mijlö Skriva text på skärmen Värdesiffror Variabler och typer Strängar Makro Vektorer

C-programmering, föreläsning 2 Jesper Wilhelmsson

TDDC77 Objektorienterad Programmering

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

Introduktionslaboration

Klasser och objekt, referenser Grundkurs i programmering med Python

Övning från förra gången: readword

Tentamen i Programmering grundkurs och Programmering C

Kompilering och exekvering. Föreläsning 1 Objektorienterad programmering DD1332. En kompilerbar och körbar java-kod. Kompilering och exekvering

2D1339 Programkonstruktion för F1, ht 2004

GPT föreläsning 8. Förra veckan: Man kan ta tiden på en sorterad teckensträng Förra gången: Problemlösning på lägre nivå kan sortera funktioner

Programmering A C# VT Ett kompendie över Programmering A (50p) i c# Stefan Fredriksson

Objektorienterad programmering Föreläsning 4

Objektorienterad programmering

Föreläsning 3-4 Innehåll. Diskutera. Metod. Programexempel med metod

EDAA20 Programmering och databaser. Mål komprimerat se kursplanen för detaljer. Om att lära sig programmera. Föreläsning 1-2 Innehåll.

Översikt 732G11 PROGRAMMERING 1. Personal. Kursens mål. Litteratur. Kursens innehåll

Testning. 1. Inledning

Funktioner. Linda Mannila

Föreläsning 3-4 Innehåll

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

Datalogi I, grundkurs med Java 10p, 2D4112, Fiktiv tentamen, svar och lösningar och extra kommentarer till vissa uppgifter 1a) Dividera förs

F5: Högnivåprogrammering

Introduktion till algoritmer - L0 - Grunder i C++ Matematikgymnasiet, Läsåret L0 - Grunder i C++

F5: Högnivåprogrammering

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

Funktioner. Jan Erik Moström,

Skizz till en enkel databas

Anteckningar 1: Grundläggande saker

int iarray[]= new int[3]; // deklarera ett heltalsfält med tre heltal int jarray[]={ 1, 3, 5, 7, 9, 11, 13, 15}; // initierat fält 8 element

Grundkurs i programmering, 6 hp (725G61) Dugga 2 tillfälle 2

Översikt. Installation av EasyPHP 1. Ladda ner från Jag använder Release Installera EasyPHP.

Transkript:

1 Funktioner och procedurell abstraktion Det som gör programkonstruktion hanterlig och övergripbar och överhuvudtaget genomförbar är möjligheten att dela upp program i olika avsnitt, i underprogram. Vår förmåga att hantera ett stort komplext problem bygger till stor del på vår förmåga att dela upp problemet i mindre delar och därefter lösa var del för sig. Detta är kärnan i procedurell abstraktion. Procedurell abstraktion förenkling genom uppdelning Man kan enkelt ge exempel på procedurell abstraktion i vardagslivet Exempel, frukosttillagning medelst procedurell abstraktion 1 Koka kaffe 2 Stek två ägg 3 Gör en skinkmacka Detta är en anständig beskrivning av tillagningen av en frukost. Beskrivningen består av tre olika procedurer. Beskrivningen är abstrakt, det vill säga förenklad. Förenklingen/abstraktionen består i att man inte beskriver varje enskild detalj i exempelvis proceduren Koka kaffe. Denna förenkling kan ske på flera olika nivåer. Den enklaste kan vara att helt enkelt ange Laga frukost. En mindre abstrakt variant är de tre stegen som är beskrivna ovan. En ännu mindre abstrakt variant vore om man ytterligare beskrev de olika stegen, ex 1. Koka kaffe: Ta fram kaffepulver, häll 5 dl vatten i bryggaren, mät upp 7 mått kaffepulver i filtret, slå på bryggaren, vänta 2 minuter. Denna förfining kan dras in absurdum såsom exempelvis att ange exakt vila armrörelser och benrörelser man ska utföra föra att hälla 5 dl vatten i någon speciell kaffebryggare. Om man utformar dessa procedurer mer och mer exakt kommer samtidigt beskrivningen att bli mer och mer specialiserad. En angivelse av benrörelser fungerar troligtvis bara för ett speciellt kök, med speciellt placerade köksverktyg, medan den första beskrivningen fungerar i de flesta kök. Vid programmering kommer man aldrig att behöva förfina mer än att det direkt går att översätta till programsatser, eller till välkända lösningar på standardproblem. För att åstadkomma denna uppdelning i procedurer eller underprogram skriver man funktioner. 1.1 Funktioner Av de funktioner vi redan stött på kan vi utläsa på vilket sätt funktioner kommer att anropas. En funktion/ett funktionsanrop representerar ett återanvändbart programavsnitt som utförs då programmet stöter på ett anrop. Utdrag ur Exempel för användning av texthanteringsfunktioner // tilldelning namn1 > namn1och2 strcpy( namn1och2, namn1 ); // lägg till texten ", "

strcat(namn1och2, ", "); // lägg till namn2 strcat(namn1och2, namn2); strcpy( namn1och2, namn1 ); är ett funktionsanrop till en redan skriven funktion som utför det arbete som funktionen strcpy antyder, att genom en iteration kopiera över alla tecken i texten namn1 till textfältet namn1och2. Det är en liknande iteration som vi såg göras av en for sats vid tilldelningsoperationen för ett textfält på sidan Error: Reference source not found. 1.1.1 Funktionsdeklaration och funktionsdefintion En funktion består huvudsakligen av två delar 1. en deklaration som berättar hur funktionen ska användas i ett program 2. en definition som beskriver vilken programkod som ska utföras vid anropet. En deklaration har följande form returtyp funktionsnamn(argumenttypslista ); I vårt tidigare skrivsätt för operationer skulle detta se ut som funktionsnamn( argumentlista): returtyp En definition har följande form returtyp funktionsnamn(argumentdeklarationslista) sats/satsblock; Returtyperna och argumentlistorna måste stämma överens exakt med avseende på datatyperna. Den enklaste datatypen är void (ingenting) den använder man om man inte vill ge något värde till eller från funktionen. De funktioner som har returtyp void ger alltså inget returvärde. Dessa funktioner är av en speciell kategori funktion kallade procedurer. Författaren anser att distinktionen mellan sk. void funktioner(procedurer) och icke void funktioner (funktioner) är onödig, men eftersom många andra gör denna distinktion vill jag påpeka att den förekommer. Det finns däremot anledning att först i en text behandla void funktioner eftersom de är den syntaktiskt enklaste typen. Den enklast möjliga funktionsdeklarationen ser ut som // dra_linje ritar ett streck med tecken void dra_linje(); Kommentaren krävs förstås inte av kompilatorn men det är en god vana att kommentera varje funktionsdeklaration, så att man enkelt kan läsa ut syftet med funktionen.

En enkel definition för deklarationen kan se ut som void dra_linje() cout<<" "<<endl; #include<iostream> using namespace std; Kom ihåg att syftet med deklarationen är att berätta för både kompilator och användare hur funktionen ska användas. Definitionen utnyttjas sedan vid länkning för att koppla ihop anrop med programkod. När man skriver ett huvudprogram som använder funktioner bör man komma ihåg att syftet med funktionerna är procedurell abstraktion. Därför bör man ha deklarationerna väl synliga och lättillgängliga vid skrivandet av huvudprogrammet main(). Det är dessutom så att kompilatorn måste tolka deklarationer innan dess definitioner. I annat fall kommer definitionen att även tolkas som en deklaration (deklaration och definition på samma gång) och den efterföljande deklarationen kommer att betraktas som en dubbeldeklaration eller nydeklaration, vilket inte är tillåtet. I ett kort program kan vår funktionsdeklaration och funktionsdefinition fogas in som // Lätttillgängliga deklarationer // dra_linje ritar ett streck med tecken void dra_linje(); int main() dra_linje(); // anropa underprogram cout<<"hello World"<<endl; dra_linje(); return 0; void dra_linje() cout<<" "<<endl; Programmet anropar funktionen dra_linje två gånger. Vid varje anrop styrs programflödet över till satsblocket till funktionen, rad 17: cout<<" " kommer alltså att exekveras två gånger. När satsblocket till funktionen är slut styrs programflödet tillbaka till det anropande uttrycket. Då kompilatorn stöter på anropet till funktionen måste den ha sett en deklaration av funktionen som anropas. Resultatet blir:

Hello World Press any key to continue 1.1.2 Övning: int dra_linje() Prova att i din utvecklingsmiljö ändra definitionens första rad till int dra_linje(); Observera vilka fel som rapporteras vid kompilering / länkning Ändra tillbaka definitionen till det ursprungliga och ändra istället deklarationen till Observera vilka fel som rapporteras vid kompilering / länkning Funktionsnamn är om möjligt ännu viktigare än variabelnamn. Använd utförliga och tydliga funktionsnamn som beskriver dess syften väl. En funktion som aldrig anropas körs aldrig. Det kan mycket väl tänkas att du skrivit dina funktion korrekt i ditt program, men programmet gör ändå inte som du vill. Ibland beror det på att du glömt anropet av funktionen. Detta är ett fel som kompilatorn inte kan upptäcka. 1.2 Funktioner som behöver indata Vi har sett tidigare i samband med texthanteringen hur vi kunde berätta för funktionen att den skulle göra beräkningar på någon viss variabel, exempelvis den tidigare satsen int len = strlen( namn_1 ); utför en beräkning på variabeln namn_1 för att kontrollera hur många tecken som texten innehåller. Denna data meddelas genom argumenttyper och argumentnamn Den tidigare funktionen dra_linje() som drar ett streck av minustecken är inte vidare flexibel. Man kan till exempel inte ange hur långt strecket ska vara. Det kan man enkelt åstadkomma med funktionsargument. Detta skulle i huvudprogrammet kunna se ut som:

int main() dra_linje( 12 ); // skriv tolv minustecken cout<<"hello World"<<endl; dra_linje( 5 ); // skriv fem minustecken return 0; Siffrorna 12 och 5 kallas aktuella argument. Notera att antalet minustecken är ett heltal ( int ), en deklaration kan därför skrivas som // dra_linje(int ) ritar ett streck med ett visst antal tecken void dra_linje(int ); Detta är inte samma funktion som tidigare utan en ny funktion. På samma sätt som operatorer identifieras en funktion med hjälp av dess signatur, dvs. namn + argumenttyper. Våra funktioners signaturer är dra_linje() respektive dra_linje(int ). Notera att returtypen inte ingår i signaturen, det innebär att det kan inte finnas en funktioner döpt int dra_linje() samtidigt som en funktion void dra_linje(). I syntaxen för en funktionsdeklaration och definition anger man en argumenttypslista respektive argumentdeklarationslista Vi kan skriva en funktionsdefintion som void dra_linje(int antal_minus) for(int index=0; index< antal_minus; index++) cout<<" "; cout<<endl; Rad 1: Det görs nu en variabeldeklaration varje gång funktionen anropas. Variabeln inititeras med det värde som anges som aktuellt argument. Variabeln antal_minus kallas formellt argument. Det är det formella argumentet som används i funktionens programkod. Rad 3 6: Repetitionen skriver ut lika många minustecken som värdet i variabeln antal_minus.

#include<iostream> using namespace std; I ett komplett program kan de båda funktionerna skrivas och användas som // dra_linje ritar ett streck med tecken void dra_linje(); // dra_linje(int ) ritar ett streck med ett visst antal tecken void dra_linje(int ); int main() dra_linje(); // anropa funktion cout<<"hello World"<<endl; dra_linje(); dra_linje( 5 ); cout<<"hello"<<endl; dra_linje( 78 ); return 0; void dra_linje() cout<<" "<<endl; void dra_linje(int antal_minus) for(int index=0; index< antal_minus; index++) cout<<" "; cout<<endl; Programkörning går till som : Start vid main() Funktionsanropet dra_linje() identifieras som funktionen void dra_linje(), funktionen anropas, cout satsen utförs. Texten "Hello World" skrivs ut Funktionsanropet dra_linje() identifieras som samma funktion void dra_linje(), funktionen anropas, cout satsen utförs. Funktionsanropet dra_linje( 5 ) identifieras som void dra_linje( int ). Funktionen anropas med aktuellt argument 5, Funktionen anropas. I funktionen void dra_linje( int ): Argument deklarationen blir int antal_minus = 5. Repetitionssatsen deklarerar ytterligare ett heltal int index = 0. Iterationen skriver ut 5 minustecken.

När funktionens satsblock tar slut upphör variablerna antal_minus och index att vara meningsfulla, och de förstörs därför. Man säger att de har sin räckvidd (eng. scope) inom funktionen. Funktionen styr programflödet tillbaka till cout<<"hello"; Funktionsanropet dra_linje( 78 ) identifieras som void dra_linje( int ). Funktionen anropas med aktuellt argument 78. I funktionen void dra_linje( int ): Argument deklarationen blir int antal_minus = 78. Observera att detta är variabel nummer två med namnet antal_minus som deklareras. (den första har förstörts). Repetitionssatsen deklarerar variabeln index = 0 för andra gången. Iterationen skriver ut 78 minustecken. Funktionen styr programflödet tillbaka till programslut. Det centrala i detta program är återigen abstraktionen/förenklingen av att rita en linje. Då funktionerna dra_linje väl är skrivna är det inte längre intressant på vilket sätt de fungerar utan bara att de fungerar som de är deklarerade. Detta försöker man alltid sträva efter då man utformar sina program. Det är värt att notera att i funktionsdeklarationen har man tillåtelse att ge identifierare för det olika argumenten, för funktionen dra_linje(int ) skulle deklarationen kunna se ut som void dra_linje(int antal_tecken); Syftet med identifieraren är endast att upplysa den person som läser deklarationen om syftet med heltalet. Kompilatorn eller programmet tar ingen som helst hänsyn till den identifierare som skrivs i deklarationens argumentlista. Definitionen använder ju deklarationernas identifierare som variabler inuti funktionskroppen. 1.3 Funktioner som returnerar värden Ofta vill man att en funktion ska utföra en beräkning eller komma fram till något numeriskt resultat. Vi har tidigare sett en funktion som beräknar längden på en text int len = strlen( namn_1 ); Denna funktion ger tillbaka/utvärderas till ett heltalsvärde. Operationen kan beskrivas som strlen(char * ): int Heltalstypen anger som vanligt att uttrycket utvärderas till ett heltal. Vi kan konstruera egna funktioner med liknande utseende. För att beräkna arean av en rektangel tar man basen * höjden. Detta kan förstås skrivas som en funktion. I ett huvudprogram kan man tänka sig att funktionen anropas som

double bredd, hojd, yta; bredd= 5.0; hojd= 2.5; yta= area( bredd, hojd ); Funktionen utvärderas som ett flyttal och tar två flyttal som argument. Deklarationen blir då double area( double, double); Funktionsdefinitionen innehåller en enkel multiplikation. double area( double b, double h) double a = b * h; return a; Alternativt kan man skriva funktionen på ett enklare (men mindre tydligt) sätt som double area( double b, double h) return b*h; return satsen anger alltså vilket värde som funktionen ska utvärderas till. Datatypen för uttrycket i return satsen måsta vara av samma datatyp som, eller kunna omvandlas till, returtypen angiven i deklaration och definition. Satsblocket som hör till en funktion kallas ofta funktionens implementation. Då man talar om implementering eller implementation avser man programkoden eller skrivandet av programkoden. Funktioner ska skrivas med målet att de ska fungera i så många situationer som möjligt. Man talar om generella funktioner. Det leder oss direkt in på ett mycket vanligt nybörjarmisstag vid implementation av funktioner. En funktion ska aldrig innehålla in eller utmatningssatser om det inte uttryckligen är funktionens syfte. Area funktionen i tidigare exempel fungerar bra för att visa på nackdelarna med detta. Antag att man skrivit funktionen som

//Deklaration double area(); //Definition double area() double b,h; cout<<"ange rektangelns bredd:"; cin>>b; cout<<"ange rektangelns höjd:"; cin>>h; return b*h; Funktionen kan mycket väl vara lämpad för uppgiften i ett speciellt fall, men den är långt ifrån så generell som den tidigare area beräkningen. Antag att programmet redan kände till värden för bredd och höjd. Då skulle inmatningssatserna förmodligen göra programmet väldigt förvirrande för användaren, om inte rent obrukbart. Undantaget är alltså funktioner som uttryckligen är till för in och utmatning. Typexempel är funktioner typ dra_linje ovan. Funktioner för utmatning är väldigt ofta void funktioner (procedurer). 1.4 Speciella datatyper för funktionsargument 1.4.1 Fälttyper Man kan ge textfält som argument till funktioner på samma sätt som man ger vanliga variabler som argument. Det man måste hålla i minnet är att fältvariabeln inte representerar själva texten utan bara vart texten börjar. Detta får vissa konsekvenser för texter i funktioner. Betrakta programmet

#include<iostream> using namespace std; void skriv_10_ggr(char []); int main() char text1[]="ett"; char text2[]="två"; skriv_10_ggr( text1 ); skriv_10_ggr( text2 ); return 0; void skriv_10_ggr( char txt[]) for(int i = 0;i<10;i++) cout<< txt; Programmet ger följande utskrift EttEttEttEttEttEttEttEttEttEttTvåTvåTvåTvåTvåTvåTvåTvåTvåTvåPress any key to continue Det aktuella argumentet i första funktionsanropet är alltså adressen till den minnescell som innehåller tecknet 'E' i texten Ett. Argumentet är alltså ett slags heltal. Detta innebär att den information som behöver föras över till funktionen inte är hela texten, vilket skulle kunna bli väldigt resurskrävande om texten var lång, utan bara adressen till textens första tecken. Variabeln txt och variablerna text1 och text2 representerar alltså inte bara lika texter utan samma texter vid respektive funktionsanrop. Alltså txt==text1 sedan txt==text2, text1 och text2 är naturligtvis aldrig lika. Detta har ytterligare en effekt, förutom att vara resurseffektivt. Man kan nämligen manipulera innehållet i fältet inuti funktionen. Se exempelvis funktionen och anropet

void mata_in_textrad(char txt[]); void mata_in_tal( int ); int main() char inmatningsyta[200]; int talet; mata_in_textrad( inmatningsyta ); mata_in_tal( talet ); // går ej cout<<"du har matat in:"<< inmatningsyta<<endl; cout<<"och talet: "<<talet<<endl; return 0; void mata_in_textrad(char txt[]) cin.getline( txt, 80); void mata_in_tal( int tal) cin>>i; Det fält som skapas i och med deklarationen char inmatningsyta[200]; används direkt i funktionen eftersom variabeln inmatningsyta och txt (i funktionen mata_in_textrad) avser samma minnesyta med 200 tecken. Detta fungerar inte med vanliga datatyper som i funktionen mata_in_tal(int ) eftersom de deklareras som nya variabler oberoende av den anropande funktionens variabler. Dessa egenheter motiverar två speciella datatyper konstanter och referenser. 1.4.2 Konstanter Man kan definiera upp konstanter i c++ genom nyckelordet const. const double PI = 3.14159265358; const int NOLL = 0; const char ALFABET[] = "abcdefghijklmnopqrstuvwxyzåäö"; Konstanter har ofta identifierare som bara består av versaler. Den sista deklarationen skall läsas som ett fält bestående av const char. Tecknen i fältet får inte ändras. Att deklarera en variabel som konstant gör att man inte har tillåtselse att ändra variabelns värde. Samtliga följande satser är otillåtna PI = 3.14; NOLL += 1; ALFABET[3] = 'D'; // otillåtet för const double // otillåtet för const int // otillåtet för const char För funktioner innebär det att om den tidigare funktionen mata_in_textrad( char [] ) istället skulle skrivits som

void mata_in_textrad(const char txt[]); // och definition void mata_in_textrad(const char txt[]) cin.getline(txt, 80); är det en otillåten operation att ändra värdet på tecknen i fältet. cin.getline( txt, 80) är då en otillåten operation, kompilatorn ger felmeddelande, eftersom satsen ändrar innehållet i fältet. Jämför deklarationerna av texthanteringsfunktionerna i cstring. 1.4.3 Referenser int i = 3; int & ref = i; En annan speciell deklaration får man om man deklarerar en variabel som referens. Detta ser ut som Rad 2: Deklarerar identifieraren ref att vara en så kallad referens. En referensvariabel är en synonym till en redan existerande variabel. Referensen fungerar på exakt samma sätt som den ursprungliga variabeln. Genom referensen får man alltså här två variabelnamn/identifierare att referera till exakt samma data. Betrakta int i = 3; int j = 4; int & ref = i; ref = j; // obs tilldelning värdet i j kopieras till ref/i i++; cout<<"i:"<<i<<endl; cout<<"j:"<<j<<endl; cout<<"ref:"<<ref<<endl; ref++; cout<<"i:"<<i<<endl; cout<<"j:"<<j<<endl; cout<<"ref:"<<ref<<endl;

Programsnutten ger resultatet i:5 j:4 ref:5 i:6 j:4 ref:6 Detta kommer sig alltså av att ref och i representerar samma instans (samma faktiska heltal). Tilldelningssatsen på rad 4 ger alltså endast värdet av j till instansen i/ref. Med tanke på att referenser är synonymer till redan existerande instanser måste de initieras i samband med en deklaration, detta görs automatiskt om man gör dem till funktionsargument (de initieras då med de aktuella argumenten), men inte om man deklarerar dem som ovan. Följande sats är otillåten eftersom den inte refererar till något existerande heltal. int & j; int & k = 4; // otillåtet 4 är ingen heltalsvariabel I exempel som detta är det svårt att se nyttan med referenser. Nyttan blir tydligare om man visar hur det fungerar för ett funktionsargument. Betrakta funktionen och programmet void mata_in_tal( int&, int &); int main() int tal1, tal2; cout<<"mata in ett tal"<<endl; mata_in_2_tal( tal1, tal2 ); cout<<"du har matat in "<<tal; return 0; void mata_in_tal( int& i, int& j) cin>>i>>j; Denna programsnutt fungerar som tänkt eftersom de identifierare som deklarerats i funktionen, i och j, är synonymer till redan existerande variabler tal1 respektive tal2. De refererar till samma heltal. Se även funktionen swap( int&, int& ) i avsnittet standardalgoritmer.