{"id":14,"date":"2008-10-16T10:22:09","date_gmt":"2008-10-16T08:22:09","guid":{"rendered":"http:\/\/www.kristiansborg.dk\/bibliotek\/?page_id=14"},"modified":"2008-10-16T10:22:09","modified_gmt":"2008-10-16T08:22:09","slug":"objektorienteret-programmering-i-c","status":"publish","type":"page","link":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/objektorienteret-programmering-i-c\/","title":{"rendered":"Objektorienteret programmering i C++"},"content":{"rendered":"<p><strong><br \/>\n<\/strong><\/p>\n<p><strong>Indhold<\/strong><\/p>\n<p>Indledning&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;.. 2<\/p>\n<p>Hvordan en klasse erkl\u00e6res&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230; 2<\/p>\n<p>Angivelse af funktioner&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;. 3<\/p>\n<p>Constructor&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230; 3<\/p>\n<p>Erkl\u00e6ring af et objekt&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230; 4<\/p>\n<p>Requests (kald af medlemsfunktioner)&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230; 5<\/p>\n<p>Konstante objekter&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230; 5<\/p>\n<p>Multiple constructors&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;. 6<\/p>\n<p>Alternativ assignment-metode i constructors&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230; 7<\/p>\n<p>Operator overloading&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230; 7<\/p>\n<p>Friend-funktioner&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;. 11<\/p>\n<p>Dynamisk instantiering af objekter&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;. 12<\/p>\n<p>Copy constructor&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;. 13<\/p>\n<p>Destructor&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230; 14<\/p>\n<p>Kald af funktioner gennem pointere&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;.. 15<\/p>\n<p>Templates&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230; 16<\/p>\n<p>Nedarvning&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;. 18<\/p>\n<p>Polymorfi&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;. 21<\/p>\n<p>Multipel nedarvning&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;. 22<\/p>\n<p>Virtuelle nedarvning&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;. 23<\/p>\n<p>Abstrakte klasser&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;. 25<\/p>\n<p>Statiske funktioner&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230; 26<\/p>\n<h2>\n<a name=\"_Toc390869072\">Indledning<\/a><\/h2>\n<p>Objekt-orienteret programmering er ikke bare en ny m\u00e5de at programmere p\u00e5. Det er en helt ny m\u00e5de at t\u00e6nke p\u00e5. I stedet for at se sit program som opbygget af algoritmer, der kan opdeles i funktioner, skal man t\u00e6nke p\u00e5 sit program som best\u00e5ende af objekter, der alle har specielle egenskaber. At l\u00e6re at udnytte de objekt-orienterede muligheder i sit programmeringssprog er ikke det store problem, men \u00e6ndringen af tankegangen kommer f\u00f8rst med tiden.<\/p>\n<p>\u00a0<\/p>\n<p>Grundstenen i objekt-orienteret programmering er &#8211; ikke overraskende &#8211; objekter. Objekter er imidlertid ikke bare objekter; de er objekter af en bestemt type. Objekters type kaldes deres klasse.<\/p>\n<p>\u00a0<\/p>\n<p>Det er muligt at lave flere objekter af samme klasse. Disse vil s\u00e5 &#8211; til at starte med &#8211; v\u00e6re identiske. Med tiden vil de naturligvis udvikle sig forskelligt alt efter hvilke funktioner, der bliver kaldt p\u00e5 dem.<\/p>\n<p>\u00a0<\/p>\n<h2><a name=\"_Toc390869073\">Hvordan en klasse erkl\u00e6res<\/a><\/h2>\n<table style=\"height: 192px;\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" width=\"565\" align=\"left\">\n<tbody>\n<tr>\n<td height=\"192\" align=\"left\" valign=\"top\"><strong>class <\/strong>Cirkel {<\/p>\n<p>\u00a0 <strong>private:<\/strong> \/\/Private variable<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int<\/strong> radius;<\/p>\n<p>\u00a0 <strong>public:<\/strong> \/\/Member functions<\/p>\n<p>\u00a0\u00a0\u00a0 Cirkel(int r = 0); \/\/Constructor<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>void<\/strong> SetRadius (int);<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int<\/strong> GetAreal();<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int<\/strong> GetOmkreds();<\/p>\n<p>};<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 1<\/p>\n<p>\u00a0<\/p>\n<p>Eksempel 1 viser, hvordan en klasse erkl\u00e6res. Som det ses starter man med det reserverede ord <em>class<\/em>. Derefter gives navnet p\u00e5 klassen eller typen, hvorefter en kr\u00f8llet parentes f\u00f8lger.<\/p>\n<p>\u00a0<\/p>\n<p>Klasser kan indeholde to forskellige ting: Variable og funktioner. De er opdelt i to forskellige grupper. De private variable og funktioner og de offentlige variable og funktioner. Det er hovedsageligt variable, der er private, mens de fleste funktioner er offentlige, men det modsatte kan ogs\u00e5 v\u00e6re tilf\u00e6ldet.<\/p>\n<p>\u00a0<\/p>\n<p>De private variable indledes med ordet <em>private:<\/em>. Herefter f\u00f8lger variabel-definitionerne, ganske som i en almindelig funktion. Det specielle ved private variable er, at de kun kan tilg\u00e5s fra de funktioner, der er medlemmer af klassen. Konceptet med private variable kaldes indkapsling. Det vil sige, at de data, der kun vedr\u00f8rer selve objektet, er afsk\u00e6rmet fra resten af programmet.<\/p>\n<p>\u00a0<\/p>\n<p>De offentlige variable og funktioner indledes med ordet <em>public:<\/em>. Disse kan tilg\u00e5s fra hele programmet &#8211; hvordan vender vi tilbage til.<\/p>\n<p>\u00a0<\/p>\n<p>Funktioner i en klasse kaldes medlemsfunktioner eller member functions. Et funktionskald kaldes en request.<\/p>\n<p>\u00a0<\/p>\n<p>Bem\u00e6rk at der <em>skal<\/em> v\u00e6re et semikolon efter den afsluttende kr\u00f8llede parentes.<\/p>\n<p>\u00a0<\/p>\n<p>Da den private variabel radius ikke kan tilg\u00e5s af andre funktioner end medlemsfunktionerne er det n\u00f8dvendigt, at have en funktion, der s\u00e6tter en ny radius. Den kaldes i dette eksempel SetRadius. Dette kan m\u00e5ske virke meget uhensigtsm\u00e6ssigt, men det er faktisk en af fordelene ved objekter. Da SetRadius er den eneste funktion, der \u00e6ndrer variablen radius ved vi, at hvis radius pludseligt antager en forkert v\u00e6rdi, s\u00e5 m\u00e5 \u00e6ndringen v\u00e6re sket gennem funktionen SetRadius &#8211; det letter fejlretningen.<\/p>\n<p>\u00a0<\/p>\n<p>I praksis vil der ofte v\u00e6re andre fordele ved indkapslingen. Man kan for eksempel forestille sig, et konto-objekt, der har en funktion, der tilskriver rente. Hvis reglerne for rentetilskrivning skal \u00e6ndres, er det kun n\u00f8dvendigt at \u00e6ndre denne ene funktion, og da kontoens saldo er privat, er det ikke muligt, at en travl programm\u00f8r falder for fristelsen til lige at l\u00e6gge et par procent til saldoen, og s\u00e5 er den rentetilskrivning ordnet.<\/p>\n<h2><a name=\"_Toc390869074\">Angivelse af funktioner<\/a><\/h2>\n<p>I erkl\u00e6ringen af klassen skrives funktioner bare med deres prototype. N\u00e5r selve funktionen skal angives, skal man imidlertid f\u00f8rst angive, hvilken klasse funktionen h\u00f8rer til. Funktionshovedet vil have f\u00f8lgende format:<\/p>\n<p>\u00a0<\/p>\n<p>&lt;returtype&gt; &lt;klasse&gt;::&lt;funktionsnavn&gt; (&lt;parametre&#8230;&gt;)<\/p>\n<p>\u00a0<\/p>\n<p>Eksempler p\u00e5 dette kan ses i eksempel 2. Herefter f\u00f8lger funktionskroppen som i en almindelig funktion. Dobbelt-kolonet, der adskiller klasse og funktionsnavn, kaldes scope.<\/p>\n<h2><a name=\"_Toc390869075\">Constructor<\/a><\/h2>\n<p>Som det ses i eksempel 1, st\u00e5r der &#8220;Constructor&#8221; i kommentaren efter medlemsfunktionen Cirkel(int r=0). En constructor er en funktion, der kaldes automatisk, n\u00e5r der oprettes et objekt af klassen. Det normale arbejde for constructor-funktionen er at initialisere variable, og det er ogs\u00e5 det, der er form\u00e5let med denne constructor. Parameteren r angiver radius &#8211; p\u00e5 den m\u00e5de kan cirkel-objektet i programmet initialiseres til at have en startv\u00e6rdi.<\/p>\n<p>\u00a0<\/p>\n<p>Hvis der ikke gives en startv\u00e6rdi, bliver r sat til default-v\u00e6rdien 0. Herefter udf\u00f8res den kode, der st\u00e5r i funktionen Cirkel::Cirkel.<\/p>\n<p>\u00a0<\/p>\n<p>Constructors skal altid have det samme navn som klassen.<\/p>\n<p>\u00a0<\/p>\n<p>Af eksempel 1 ses det ogs\u00e5, at der ikke angives nogen returtype for constructor&#8217;en. Det betyder ikke som normalt, at returtypen er int. Constructors kan ikke returnere noget, og derfor angiver man ingen returtype.<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\">#include &lt;iostream.h&gt;<\/p>\n<p>#include &lt;math.h&gt;<\/p>\n<p>\u00a0<\/p>\n<p>#define pi M_PI<\/p>\n<p>\u00a0<\/p>\n<p><strong>class <\/strong>Cirkel {<\/p>\n<p>\u00a0 <strong>private:<\/strong> \/\/Private variable<\/p>\n<p>\u00a0\u00a0\u00a0 int radius;<\/p>\n<p>\u00a0 <strong>public:<\/strong> \/\/Member functions<\/p>\n<p>\u00a0\u00a0\u00a0 Cirkel(int r = 0); \/\/Constructor<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>void<\/strong> SetRadius (int);<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int<\/strong> GetAreal();<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>GetOmkreds();<\/p>\n<p>};<\/p>\n<p>\u00a0<\/p>\n<p>Cirkel::Cirkel(<strong>int<\/strong> r)<\/p>\n<p>{<\/p>\n<p>\u00a0 radius = r;<\/p>\n<p>}<\/p>\n<p>\u00a0<\/p>\n<p><strong>void <\/strong>Cirkel::SetRadius (<strong>int<\/strong> r)<\/p>\n<p>{<\/p>\n<p>\u00a0 radius = r;<\/p>\n<p>}<\/p>\n<p>\u00a0<\/p>\n<p><strong>int <\/strong>Cirkel::GetAreal()<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>return<\/strong> pi*radius*radius;<\/p>\n<p>}<\/p>\n<p>\u00a0<\/p>\n<p><strong>int <\/strong>Cirkel::GetOmkreds()<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>return<\/strong> 2*pi*radius;<\/p>\n<p>}<\/p>\n<p>\u00a0<\/p>\n<p><strong>void <\/strong>main()<\/p>\n<p>{<\/p>\n<p>\u00a0 Cirkel rund(5);<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0 cout &lt;&lt; &#8220;Omkredsen er &#8221; &lt;&lt; rund.GetOmkreds() &lt;&lt; endl;<\/p>\n<p>}<\/p>\n<p>\u00a0<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 2.<\/p>\n<h2><a name=\"_Toc390869076\">Erkl\u00e6ring af et objekt<\/a><\/h2>\n<p>Et objekt erkl\u00e6res p\u00e5 samme m\u00e5de som alle andre variable. Det vil sige p\u00e5 formen<\/p>\n<p>&lt;datatype&gt; &lt;navn&gt;<\/p>\n<p>\u00a0<\/p>\n<p>Hvis man i stedet for at definere en int ved navn x, vil definere et objekt af typen Cirkel med navnet rund, skriver man alts\u00e5 ikke <strong>int <\/strong>x; men Cirkel rund;<\/p>\n<p>Ligesom man kunne initialisere simple variable (fx <strong>int<\/strong> x=5;)\u00a0 kan man ogs\u00e5 initialisere komplekse variable som objekter, hvis klassen tillader det. Det g\u00f8r den i dette tilf\u00e6lde (constructeren tager parameteren r). Derfor kan man, hvis man vil initialisere rund med radius 5, skrive Cirkel rund(5);<\/p>\n<p>\u00a0<\/p>\n<h2><a name=\"_Toc390869077\">Requests (kald af medlemsfunktioner)<\/a><\/h2>\n<p>N\u00e5r man har brug for at benytte en af de offentlige funktioner, der findes i objektet sender man et request. Det g\u00f8res p\u00e5 samme m\u00e5de som man foretager et funktionskald. Blot skal man huske at angive, hvilket objekt man kalder funktionen i. Bem\u00e6rk, at det skal v\u00e6re objektet (alts\u00e5 variablen), man angiver, og ikke klassen. Objektnavnet og funktionsnavnet adskilles med punktum (der udtales &#8220;dot&#8221;), s\u00e5 requesten har f\u00f8lgende format:<\/p>\n<p>\u00a0<\/p>\n<p>&lt;objekt&gt;.&lt;funktion&gt;(&lt;parametre&gt;);<\/p>\n<p>\u00a0<\/p>\n<p>Et eksempel p\u00e5 en request ses i main-delen af eksempel 2.<\/p>\n<h2><a name=\"_Toc390869078\">Konstante objekter<\/a><\/h2>\n<p>Som alle andre variable kan objekter ogs\u00e5 g\u00f8res konstante. Det g\u00f8res ved at skrive <em>const<strong> <\/strong><\/em>foran deres definition. Fx <strong>const <\/strong>Cirkel rund(5);<\/p>\n<p>\u00a0<\/p>\n<p>Det vil i det tilf\u00e6lde ikke v\u00e6re muligt at \u00e6ndre nogen variable i objektet. Deraf kan man slutte at funktionen SetRadius heller ikke m\u00e5 kaldes, da den jo netop \u00e6ndrer variablen radius (rent teknisk kan det godt lade sig g\u00f8re, men det giver advarslen &#8220;Non-const function Cirkel::SetRadius(int) called for const object&#8221;). Derimod skulle man tro, at det ville v\u00e6re helt i orden at kalde funktionerne GetOmkreds og GetAreal, da de jo kun l\u00e6ser radius, hvilket jo er helt legalt at g\u00f8re med konstante variable. S\u00e5dan er det imidlertid ikke. N\u00e5r et objekt er konstant er det hele objektet, der er konstant. Det vil sige, at et kald til GetOmkreds vil give en advarsel i stil med den som et kald til SetRadius gav.<\/p>\n<p>\u00a0<\/p>\n<p>Disse problemer kan imidlertid omg\u00e5s, s\u00e5 man kun f\u00e5r advarslen, n\u00e5r man virkeligt har brug for den &#8211; n\u00e5r man virkeligt foretager en \u00e6ndring af et konstant objekt. Det g\u00f8r man ved at tilf\u00f8je ordet const efter alle de medlemsfunktioner, der <em>ikke<\/em> modificerer variable. I vores eksempel vil klasse-erkl\u00e6ringen komme til at se ud som i eksempel 3. Derudover skal man huske ogs\u00e5 at tilf\u00f8je const til funktionshovedet, n\u00e5r selve funktionen skrives.<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\"><strong>class <\/strong>Cirkel {<\/p>\n<p>\u00a0 <strong>private:<\/strong> \/\/Private variable<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int<\/strong> radius;<\/p>\n<p>\u00a0 <strong>public:<\/strong> \/\/Member functions<\/p>\n<p>\u00a0\u00a0\u00a0 Cirkel(<strong>int<\/strong> r = 0); \/\/Constructor<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>void<\/strong> SetRadius (<strong>int<\/strong>);<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int<\/strong> GetAreal() <strong>const<\/strong>;<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>GetOmkreds() <strong>const<\/strong>;<\/p>\n<p>};<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 3.<\/p>\n<p>\u00a0<\/p>\n<h2><a name=\"_Toc390869079\">Multiple constructors<\/a><\/h2>\n<p>\u00a0<\/p>\n<p>Som vi tidligere har set, kan constructoren have default-v\u00e6rdier. Men betragt eksemplet med nedenst\u00e5ende constructor i class&#8217;en Point:<\/p>\n<p>\u00a0<\/p>\n<p>Point::Point (int x = 0; int y = 0);<\/p>\n<p>\u00a0<\/p>\n<p>Hvis objekter af klassen instantieres med to parametre er der ingen problemer &#8211; det er der heller ikke, hvis der slet ikke angives parametre; s\u00e5 s\u00e6ttes de begge til nul. Men hvad, hvis der kun angives et parameter? S\u00e5 antager C++, at det er det f\u00f8rste parameter, der overf\u00f8res, og de resterende s\u00e6ttes til default-v\u00e6rdier. I dette tilf\u00e6lde vil det alts\u00e5 betyde, at y s\u00e6ttes til nul. Det er meget godt, hvis det var meningen, at y skulle s\u00e6ttes til default-v\u00e6rdien, men hvad, hvis vi hellere ville have haft, at det var x, der blev sat til default-v\u00e6rdien? Den eneste m\u00e5de det kan g\u00f8res p\u00e5 med default-parametre er at bytte om p\u00e5 parametrene, og det virker meget ulogisk.<\/p>\n<p>\u00a0<\/p>\n<p>For at afhj\u00e6lpe dette problem, kan man definere flere constructors<a name=\"_ftnref1\" href=\"http:\/\/www.kristiansborg.dk\/bibliotek\/wp-includes\/js\/tinymce\/plugins\/paste\/blank.htm#_ftn1\">[1]<\/a>. I vores cirkel-eksempel vil vi alts\u00e5 kunne definere to constructors i stedet for den ene, vi har med default-v\u00e6rdier. S\u00e5 kommer erkl\u00e6ringen af klassen og implementationen af de to constructors til at se s\u00e5ledes ud:<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\"><strong>class <\/strong>Cirkel<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>private<\/strong>: \/\/Private variable<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>radius;<\/p>\n<p>\u00a0 <strong>public:<\/strong> \/\/Member functions<\/p>\n<p>\u00a0\u00a0\u00a0 Cirkel(); \/\/Constructor uden parametre<\/p>\n<p>\u00a0\u00a0\u00a0 Cirkel(<strong>int <\/strong>r); \/\/Constructor med radius som parameter<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>void <\/strong>SetRadius (<strong>int<\/strong>);<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>GetAreal();<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>GetOmkreds();<\/p>\n<p>\u00a0 };<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0 Cirkel::Cirkel ()<\/p>\n<p>\u00a0 {<\/p>\n<p>\u00a0\u00a0\u00a0 radius = 0;<\/p>\n<p>\u00a0 }<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0 Cirkel::Cirkel(<strong>int <\/strong>r)<\/p>\n<p>\u00a0 {<\/p>\n<p>\u00a0\u00a0\u00a0 radius = r;<\/p>\n<p>\u00a0 }<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 4.<\/p>\n<p>\u00a0<\/p>\n<h2><a name=\"_Toc390869080\">Alternativ assignment-metode i constructors<\/a><\/h2>\n<p>\u00a0<\/p>\n<p>Tidligere har vi i constructorens kode skrevet de assignments, der skulle foretages. Det er ogs\u00e5 muligt at skrive dem p\u00e5 en anden m\u00e5de. Fx kan vores constructor med parametren <em>r <\/em>omskrives til f\u00f8lgende:<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\">\u00a0<\/p>\n<p>\u00a0 Cirkel::Cirkel(<strong>int <\/strong>r) : radius ( r )<\/p>\n<p>\u00a0 {<\/p>\n<p>\u00a0 }<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 5.<\/p>\n<p>\u00a0<\/p>\n<p>Denne form for assignments kan kun anvendes i constructoren.<\/p>\n<p>\u00a0<\/p>\n<p>Nu da st\u00f8rrelsen p\u00e5 constructoren er begr\u00e6nset s\u00e5 den faktisk kan skrives p\u00e5 en linie, bliver det interessant at se, at man kan have koden til constructoren st\u00e5ende i klassens erkl\u00e6ring. Det kaldes inline-kode.<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\"><strong>class<\/strong> Cirkel<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>private:<\/strong> \/\/Private variable<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>radius;<\/p>\n<p>\u00a0 <strong>public:<\/strong> \/\/Member functions<\/p>\n<p>\u00a0\u00a0\u00a0 Cirkel() : radius(0) {}; \/\/Constructor uden parametre<\/p>\n<p>\u00a0\u00a0\u00a0 Cirkel(<strong>int <\/strong>r) : radius(r) {}; \/\/Constructor med radius som parameter<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>void <\/strong>SetRadius (<strong>int<\/strong>);<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int<\/strong> GetAreal();<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>GetOmkreds();<\/p>\n<p>};<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 6.<\/p>\n<p>\u00a0<\/p>\n<p>Det er smag og behag, hvilken metode man foretr\u00e6kker, men her vil vi for l\u00e6sevenlighedens skyld forts\u00e6tte med den &#8220;gamle&#8221; metode.<\/p>\n<p>\u00a0<\/p>\n<h2><a name=\"_Toc390869081\">Operator overloading<\/a><\/h2>\n<p>Operator overloading vil sige, at man tillader brug af operatorer p\u00e5 sine objekter. Normalt vil nedenst\u00e5ende jo ikke v\u00e6re tilladt:<\/p>\n<p>\u00a0<\/p>\n<p>Cirkel a,b;<\/p>\n<p>\u00a0<\/p>\n<p>if (a == b)<\/p>\n<p>cout &lt;&lt; &#8220;Ens&#8221;;<\/p>\n<p>\u00a0<\/p>\n<p>Det er imidlertid muligt at fort\u00e6lle C++-compileren, at den, n\u00e5r den m\u00f8der udtrykket &#8220;==&#8221; skal udf\u00f8re en bestemt funktion. For at g\u00f8re det, skal man bruge nogle forud-bestemte funktionsnavne. Det generelle syntaks herfor er:<\/p>\n<p>\u00a0<\/p>\n<p>&lt;returtype&gt; <strong>operator<\/strong> &lt;operator&gt; (&lt;parametre&gt;);<\/p>\n<p>\u00a0<\/p>\n<p>Antallet af parametre bruges til at kende forskel p\u00e5 un\u00e6re og bin\u00e6re operatorer. Fx er den eneste forskel p\u00e5<\/p>\n<p>\u00a0<\/p>\n<p><strong>int operator<\/strong>&#8211; ();<\/p>\n<p>og<\/p>\n<p><strong>int operator<\/strong>&#8211; (<strong>int<\/strong>);<\/p>\n<p>\u00a0<\/p>\n<p>at\u00a0 den \u00f8verste er un\u00e6rt minus (fx -5), mens den nederste er bin\u00e6rt minus (fx 3-5).<\/p>\n<p>\u00a0<\/p>\n<p>Det er ikke alle klasser, der kan g\u00f8re fornuftigt brug af alle operatorer, og s\u00e5 kan man bare n\u00f8jes med at inkludere de fornuftige &#8211; s\u00e5 kommer compileren med en fejlmeddelelse, hvis man pr\u00f8ver at bruge nogen af de andre.<\/p>\n<p>\u00a0<\/p>\n<p>I vores eksempel vil operatoren =, == og + v\u00e6re fornuftige (der kan selvf\u00f8lgeligt findes andre, men de tre giver os mulighed for at se lidt af hvert).<\/p>\n<p>\u00a0<\/p>\n<p>= s\u00e6tter vores cirkel lig med en anden cirkel &#8211; det vil sige, at radius s\u00e6ttes til radius af den anden cirkel.<\/p>\n<p>\u00a0<\/p>\n<p>== sammenligner om radius p\u00e5 to cirkler er ens og returnerer en boolsk v\u00e6rdi.<\/p>\n<p>\u00a0<\/p>\n<p>+ l\u00e6gger ikke to cirkler sammen, men l\u00e6gger en konstant til radius.<\/p>\n<p>\u00a0<\/p>\n<p>Erkl\u00e6ringen af klassen med de tre operatorer og implementationen heraf kunne se s\u00e5ledes ud:<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\"><strong>class <\/strong>Cirkel<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>private:<\/strong> \/\/Private variable<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>radius;<\/p>\n<p>\u00a0 <strong>public:<\/strong> \/\/Member functions<\/p>\n<p>\u00a0\u00a0\u00a0 Cirkel(); \/\/Constructor uden parametre<\/p>\n<p>\u00a0\u00a0\u00a0 Cirkel(<strong>int <\/strong>r); \/\/Constructor med radius som parameter<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>void <\/strong>SetRadius (<strong>int <\/strong>r);<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>GetAreal();<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>GetOmkreds();<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0\u00a0\u00a0 \/\/Operators<\/p>\n<p>\u00a0\u00a0\u00a0 Cirkel&amp;<strong> <\/strong>operator= (Cirkel);<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>operator== (Cirkel);<\/p>\n<p>\u00a0\u00a0\u00a0 Cirkel operator+ (<strong>int<\/strong>);<\/p>\n<p>};<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<p>Cirkel&amp; Cirkel::<strong>operator<\/strong>= (Cirkel c)<\/p>\n<p>{<\/p>\n<p>\u00a0 radius = c.radius;<\/p>\n<p>\u00a0 <strong>return <\/strong>*<strong>this<\/strong>;<\/p>\n<p>}<\/p>\n<p>\u00a0<\/p>\n<p><strong>int <\/strong>Cirkel::operator== (Cirkel c)<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>return <\/strong>radius == c.radius;<\/p>\n<p>}<\/p>\n<p>\u00a0<\/p>\n<p>Cirkel Cirkel::operator+ (<strong>int <\/strong>x)<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>return <\/strong>Cirkel(radius + x);<\/p>\n<p>}<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 7.<\/p>\n<p>\u00a0<\/p>\n<p>Umiddelbart kan de forskellige returtyper m\u00e5ske virke forvirrende, men pr\u00f8v at se p\u00e5 et par eksempler.<\/p>\n<p>\u00a0<\/p>\n<p>Cirkel A(5), B; \/\/Opret to cirkler &#8211; en med radius 5 og en med radius 0<\/p>\n<p>\u00a0<\/p>\n<p>B = A;<\/p>\n<p>\u00a0<\/p>\n<p>Her ser vi to objekter af samme klasse med en operator i mellem. F\u00f8rst skal det understreges, at det altid er objektet til venstre for en bin\u00e6r operator, der f\u00e5r funktionskaldet. I dette tilf\u00e6lde vil det alts\u00e5 v\u00e6re B&#8217;s funktion operator=, der kaldes.<\/p>\n<p>\u00a0<\/p>\n<p>Denne funktion skal prim\u00e6rt s\u00f8rge for, at B&#8217;s radius s\u00e6ttes lig med A&#8217;s radius. Man kunne p\u00e5 den baggrund argumentere for, at den ikke beh\u00f8vede at returnere noget. Imidlertid er det jo s\u00e5dan i C++, at assignments har en v\u00e6rdi. Man kan fx skrive X = Y = 5, hvilket medf\u00f8rer, at b\u00e5de Y s\u00e6ttes til 5 og X s\u00e6ttes til v\u00e6rdien af assignmentet Y = 5, hvilket vil sige 5. Ergo s\u00e6ttes b\u00e5de X og Y til 5.<\/p>\n<p>\u00a0<\/p>\n<p>Hvis vi \u00f8nsker, at det samme skal g\u00e6lde for objekter af cirkelklassen, fx C = B = A, skal B = A alts\u00e5 returnere v\u00e6rdien B.<\/p>\n<p>\u00a0<\/p>\n<p>At returtypen er en reference skyldes blot, at dataene fra det ene objekt ikke skal kopieres over i et andet &#8211; det har ingen betydning i dette eksempel, men ved klasser med store m\u00e6ngder private data, kan man spare tid p\u00e5 denne m\u00e5de.<\/p>\n<p>\u00a0<\/p>\n<p>Det mest interessante ved funktionen er nok at den returnerer *this. this er en pointer til det aktuelle objekt, alts\u00e5 i dette tilf\u00e6lde objektet p\u00e5 venstre-siden af lighedstegnet. At der s\u00e6ttes en stjerne foran, skyldes blot at det er v\u00e6rdien og ikke adressen, der skal returneres (at det <em>er <\/em>adressen, der bliver returneret, fordi resultatet returneres per reference, er en anden sag).<\/p>\n<p>\u00a0<\/p>\n<p>Hvis vi v\u00e6lger at sammenligne de to cirkler kan det g\u00f8res med nedenst\u00e5ende if-struktur:<\/p>\n<p>\u00a0<\/p>\n<p>if (A==B)<\/p>\n<p>cout &lt;&lt; &#8220;Ens&#8221;;<\/p>\n<p>else<\/p>\n<p>cout &lt;&lt; &#8220;Uens&#8221;;<\/p>\n<p>\u00a0<\/p>\n<p>Her skal operator== returnere en boolsk v\u00e6rdi (dvs 0 eller 1) alt efter om de to cirklers radius er ens. Det g\u00f8res i dette tilf\u00e6lde ved at returnere resultatet af sammenligningen af de to radia.<\/p>\n<p>\u00a0<\/p>\n<p>operator+ derimod skal returnere en variabel af typen Cirkel. Det ses af nedenst\u00e5ende eksempel:<\/p>\n<p>\u00a0<\/p>\n<p>B = A+2;<\/p>\n<p>\u00a0<\/p>\n<p>Her skal udtrykket A+2 evalueres f\u00f8rst. Det g\u00f8res ved et kald til A&#8217;s operator+ (A st\u00e5r p\u00e5 venstre side af operatoren). Herefter skal resultatet af denne evaluering l\u00e6gges over i B (hvilket i \u00f8vrigt sker ved et kald til B&#8217;s operator=). Da den eneste v\u00e6rdi vi kan s\u00e6tte lig med en cirkel er en anden cirkel, m\u00e5 returtypen af operator+ alts\u00e5 v\u00e6re en cirkel.<\/p>\n<p>\u00a0<\/p>\n<p>Returneringen fra operator+ viser ogs\u00e5, at man godt kan kalde en klasses constructor direkte. Returtypen herfra er et objekt af klassen.<\/p>\n<p>\u00a0<\/p>\n<p>En pudsig ting ved operator-funktioner, der returnerer objekter er, at man kan kalde member-funktioner fra assignments. Fx vil linien<\/p>\n<p>\u00a0<\/p>\n<p>cout &lt;&lt; (c+1).GetOmkreds();<\/p>\n<p>\u00a0<\/p>\n<p>udskrive omkredsen af en cirkel med en radius en st\u00f8rre end c&#8217;s (men vil ikke \u00e6ndre c&#8217;s radius!)<\/p>\n<p>\u00a0<\/p>\n<p>Ligesom det var muligt at have multiple constructors er det ogs\u00e5 muligt at have flere implementationer af den samme operator. Det foreg\u00e5r efter pr\u00e6cis samme princip som multiple constructors. P\u00e5 den m\u00e5de vil det v\u00e6re muligt &#8211; udover at l\u00e6gge en int til en cirkel &#8211; at l\u00e6gge to cirkler sammen, eller m\u00e5ske ogs\u00e5 en cirkel og en float. Hvis man arbejder med flere forskellige klasser kan man endda skrive funktioner, der g\u00f8r det muligt at sammenligne, addere osv. de forskellige klasser.<\/p>\n<p>\u00a0<\/p>\n<p>Det kan m\u00e5ske virke overraskende, at de forskellige operator-funktioner kan tilg\u00e5 variablen radius i de cirkler de f\u00e5r over som parametre. Det skyldes, at memberfunktioner i en klasse, altid kan tilg\u00e5 de private variable (og funktioner) som objekter af samme klasse har.<\/p>\n<p>\u00a0<\/p>\n<p>Det er ikke alle operatorer, der kan overloades, men de fleste kan. Nedenst\u00e5ende skema, viser hvilke der kan og ikke kan. Nogle af operatorerne vender vi tilbage til i afsnittet om friend-funktioner.<\/p>\n<p>\u00a0<\/p>\n<p>F\u00f8lgende operatorer kan overloades:<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"71\" valign=\"top\">+<\/td>\n<td width=\"71\" valign=\"top\">&#8211;<\/td>\n<td width=\"71\" valign=\"top\">*<\/td>\n<td width=\"71\" valign=\"top\">\/<\/td>\n<td width=\"71\" valign=\"top\">%<\/td>\n<td width=\"71\" valign=\"top\">^<\/td>\n<td width=\"71\" valign=\"top\">&amp;<\/td>\n<td width=\"71\" valign=\"top\">|<\/td>\n<\/tr>\n<tr>\n<td width=\"71\" valign=\"top\">~<\/td>\n<td width=\"71\" valign=\"top\">!<\/td>\n<td width=\"71\" valign=\"top\">=<\/td>\n<td width=\"71\" valign=\"top\">&lt;\u00a0<\/td>\n<td width=\"71\" valign=\"top\">&gt;\u00a0<\/td>\n<td width=\"71\" valign=\"top\">+=<\/td>\n<td width=\"71\" valign=\"top\">-=<\/td>\n<td width=\"71\" valign=\"top\">*=<\/td>\n<\/tr>\n<tr>\n<td width=\"71\" valign=\"top\">\/=<\/td>\n<td width=\"71\" valign=\"top\">%=<\/td>\n<td width=\"71\" valign=\"top\">^=<\/td>\n<td width=\"71\" valign=\"top\">&amp;=<\/td>\n<td width=\"71\" valign=\"top\">|=<\/td>\n<td width=\"71\" valign=\"top\">&lt;&lt;\u00a0<\/td>\n<td width=\"71\" valign=\"top\">&gt;&gt;\u00a0<\/td>\n<td width=\"71\" valign=\"top\">&lt;&lt;=<\/td>\n<\/tr>\n<tr>\n<td width=\"71\" valign=\"top\">&gt;&gt;=<\/td>\n<td width=\"71\" valign=\"top\">==<\/td>\n<td width=\"71\" valign=\"top\">!=<\/td>\n<td width=\"71\" valign=\"top\">&lt;=<\/td>\n<td width=\"71\" valign=\"top\">&gt;=<\/td>\n<td width=\"71\" valign=\"top\">&amp;&amp;<\/td>\n<td width=\"71\" valign=\"top\">||<\/td>\n<td width=\"71\" valign=\"top\">++<\/td>\n<\/tr>\n<tr>\n<td width=\"71\" valign=\"top\">&#8211;<\/td>\n<td width=\"71\" valign=\"top\">-&gt;<\/td>\n<td width=\"71\" valign=\"top\">,<\/td>\n<td width=\"71\" valign=\"top\">-&gt;<\/td>\n<td width=\"71\" valign=\"top\">[]<\/td>\n<td width=\"71\" valign=\"top\">()<\/td>\n<td width=\"71\" valign=\"top\"><strong>new<\/strong><\/td>\n<td width=\"71\" valign=\"top\"><strong>delete<\/strong><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u00a0<\/p>\n<p>F\u00f8lgende operatorer kan ikke overloades:<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"73\" valign=\"top\">.<\/td>\n<td width=\"66\" valign=\"top\">.*<\/td>\n<td width=\"76\" valign=\"top\">::<\/td>\n<td width=\"66\" valign=\"top\">?:<\/td>\n<td width=\"76\" valign=\"top\"><strong>sizeof<\/strong><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u00a0<\/p>\n<h2><a name=\"_Toc390869082\">Friend-funktioner<\/a><\/h2>\n<p>\u00a0<\/p>\n<p>Af og til kan man have brug for at tillade enkelte funktioner udenfor klassen at tilg\u00e5 private variable og funktioner. Det g\u00f8r man ved at inkludere funktionsnavnet i klassens erkl\u00e6ring og tilf\u00f8je det reserverede ord friend foran.<\/p>\n<p>\u00a0<\/p>\n<p>En typisk anvendelse af friend-funktioner er n\u00e5r man vil overloade en operator, hvor ens objekt st\u00e5r p\u00e5 h\u00f8jre siden. Betragt for eksempel nedenst\u00e5ende linie:<\/p>\n<p>\u00a0<\/p>\n<p>cout &lt;&lt; C;<\/p>\n<p>\u00a0<\/p>\n<p>Her vil det v\u00e6re cout, der f\u00e5r funktionskaldet, og funktioner i cout vil normalt ikke kunne tilg\u00e5 private variable i cirklen C. Derfor v\u00e6lger vi at g\u00f8re cout&#8217;s funktion til en friend af vores klasse, og vi skriver selv implementationen til udskriftsrutinen. Husk at cout blot er en variabel af typen ostream.<\/p>\n<p>\u00a0<\/p>\n<p>Erkl\u00e6ringen af klassen og implementationen af udskriftsrutinen ser s\u00e5ledes ud:<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\"><strong>class <\/strong>Cirkel<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>private:<\/strong> \/\/Private variable<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>radius;<\/p>\n<p>\u00a0 <strong>public:<\/strong> \/\/Member functions<\/p>\n<p>\u00a0\u00a0\u00a0 Cirkel(); \/\/Constructor uden parametre<\/p>\n<p>\u00a0\u00a0\u00a0 Cirkel(<strong>int <\/strong>r); \/\/Constructor med radius som parameter<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>void <\/strong>SetRadius (<strong>int <\/strong>r);<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>GetAreal();<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>GetOmkreds();<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0\u00a0\u00a0 \/\/Operators<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>void <\/strong>operator= (Cirkel);<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>operator== (Cirkel);<\/p>\n<p>\u00a0\u00a0\u00a0 Cirkel operator+ (<strong>int<\/strong>);<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>friend <\/strong>ostream&amp; <strong>operator<\/strong>&lt;&lt; (ostream&amp; ostr, Cirkel C);<\/p>\n<p>};<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<p>ostream&amp; <strong>operator<\/strong>&lt;&lt; (ostream&amp; ostr, Cirkel C)<\/p>\n<p>{<\/p>\n<p>\u00a0 ostr &lt;&lt; C.radius;<\/p>\n<p>\u00a0 <strong>return <\/strong>ostr;<\/p>\n<p>}<\/p>\n<p>\u00a0<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 8.<\/p>\n<p>\u00a0<\/p>\n<p>Bem\u00e6rk at funktionen ikke er medlem af klassen Cirkel &#8211; det vil sige, at man ikke skal inkludere klassenavnet i funktionshovedet.<\/p>\n<p>\u00a0<\/p>\n<p>At returtypen er en ostream skyldes, at man kan lave l\u00e6nkede outputs. Fx<\/p>\n<p>\u00a0<\/p>\n<p>cout &lt;&lt; &#8220;Radius er &#8221; &lt;&lt; C &lt;&lt; endl;<\/p>\n<p>\u00a0<\/p>\n<p>Hvis udskriften af C ikke returnerede en ostream, ville de ikke v\u00e6re muligt at sende endl i samme str\u00f8m.<\/p>\n<p>\u00a0<\/p>\n<p>Den ostream, der tages som parameter er den man skal sende udskriften til. Man skal alts\u00e5 v\u00e6re opm\u00e6rksom p\u00e5 ikke af gammel vane at skrive cout. Hvis man anvender cout i stedet for ostream vil funktionen kun kunne bruges til udskrift p\u00e5 sk\u00e6rmen og ikke til fx udskrift til fil.<\/p>\n<p>\u00a0<\/p>\n<p>I dette tilf\u00e6lde skal objektet ogs\u00e5 tages som parameter. Det skyldes, at denne funktion jo ikke tilh\u00f8rer klassen &#8211; hvis vi skal kende objektet, er vi n\u00f8dt til at f\u00e5 det med som parameter.<\/p>\n<p>\u00a0<\/p>\n<h2><a name=\"_Toc390869083\">Dynamisk instantiering af objekter<\/a><\/h2>\n<p>Dynamisk allokering af hukommelse er ikke nogen speciel objektorienteret funktion, men det er medtaget her, fordi det aff\u00f8der nogle interessante problemer i forhold til objekter.<\/p>\n<p>\u00a0<\/p>\n<p>Hvis vi i stedet for vores klasse Cirkel, der kun kan indeholde information om en cirkel, \u00f8nsker at lave en klasse med flere cirkler &#8211; CirkelList &#8211; kan vi opbevare informationerne om de forskellige cirkler i et privat array af typen Cirkel. St\u00f8rrelsen p\u00e5 dette array kan imidlertid variere, da vi lader det v\u00e6re op til brugeren af klassen at bestemme, hvor mange cirkler, der skal v\u00e6re plads til. Derfor har vi brug for at allokere hukommelsen dynamisk. Vi lader brugeren angive antallet af cirkler n\u00e5r han instantierer objektet. Hvis der ikke angives nogen v\u00e6rdi, vil der blive lavet plads til 10 cirkler. S\u00e5 vil erkl\u00e6ringen af klassen og constructoren komme til at se s\u00e5ledes ud:<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\"><strong>class <\/strong>CirkelList<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>private:<\/strong><\/p>\n<p>\u00a0\u00a0\u00a0 Cirkel *Liste;<\/p>\n<p>\u00a0 <strong>public:<\/strong><\/p>\n<p>\u00a0\u00a0\u00a0 CirkelList(<strong>int <\/strong>antal=10);<\/p>\n<p>};<\/p>\n<p>\u00a0<\/p>\n<p>CirkelList::CirkelList (<strong>int<\/strong> Antal)<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>if<\/strong> (Antal &lt; 1)<\/p>\n<p>\u00a0 <strong>return<\/strong>;<\/p>\n<p>\u00a0 Liste = <strong>new <\/strong>Cirkel[Antal];<\/p>\n<p>\u00a0 count = 0;<\/p>\n<p>}<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 9.<\/p>\n<p>\u00a0<\/p>\n<p>Bem\u00e6rk, at Liste, der skal v\u00e6re det array, der indeholde de forskellige cirkler, blot er en pointer &#8211; den f\u00e5r f\u00f8rst tildelt hukommelse i constructoren.<\/p>\n<p>\u00a0<\/p>\n<h2><a name=\"_Toc390869084\">Copy constructor<\/a><\/h2>\n<p>Det er tidligere n\u00e6vnt, at constructoren kaldes, n\u00e5r et objekt bliver instantieret. Pr\u00f8v at betragte nedenst\u00e5ende eksempel:<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\">\u00a0 <strong>void <\/strong>main()<\/p>\n<p>\u00a0 {<\/p>\n<p>\u00a0\u00a0\u00a0 Cirkel rund(5);<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0\u00a0\u00a0 CirkelList List1;<\/p>\n<p>\u00a0\u00a0\u00a0 List1.Add (rund);<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0\u00a0\u00a0 CirkelList List2=List1;<\/p>\n<p>\u00a0 }<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 10<\/p>\n<p>\u00a0<\/p>\n<p>Her bliver List2 instantieret og bliver omg\u00e5ende sat lig med List1. Det betyder, at alle List1&#8217;s variable bliver kopieret over til List2. Det g\u00e6lder s\u00e5ledes ogs\u00e5 pointeren List1.Liste, der peger p\u00e5 placeringen af cirklerne i hukommelsen. Det medf\u00f8rer, at det ikke er to forskellige lister vi har, men to referencer til den samme liste af cirkler. I s\u00e5danne tilf\u00e6lde har man brug for at kalde en s\u00e5kaldt copy constructor. Den kaldes automatisk, n\u00e5r der kan v\u00e6re behov for at kopiere data i constructoren. Udover ovenst\u00e5ende eksempel er det n\u00e5r et objekt gives med som parameter i et funktionskald (men ikke, hvis parameteren gives som pointer eller som reference).<\/p>\n<p>\u00a0<\/p>\n<p>Copy constructoren ser s\u00e5ledes ud:<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\"><strong>class <\/strong>CirkelList<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>private:<\/strong><\/p>\n<p>\u00a0\u00a0\u00a0 Cirkel *Liste;<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>size, count; \/\/Max. st\u00f8rrelse og antal indtastede<\/p>\n<p>\u00a0 <strong>public:<\/strong><\/p>\n<p>\u00a0\u00a0\u00a0 CirkelList(<strong>int <\/strong>antal=10); \/\/ Standard constructor<\/p>\n<p>\u00a0\u00a0\u00a0 CirkelList (const CirkelList &amp;cl); \/\/ Copy constructor<\/p>\n<p>\u00a0\u00a0\u00a0 CirkelList&amp; <strong>operator<\/strong>= (CirkelList cl);<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>void <\/strong>Add (Cirkel c); \/\/Tilf\u00f8jer cirkel<\/p>\n<p>};<\/p>\n<p>\u00a0<\/p>\n<p>CirkelList::CirkelList (<strong>const <\/strong>CirkelList &amp;cl)<\/p>\n<p>{<\/p>\n<p>\u00a0 count = cl.count;<\/p>\n<p>\u00a0 size = cl.size;<\/p>\n<p>\u00a0 Liste = <strong>new <\/strong>Cirkel [size];<\/p>\n<p>\u00a0 for (<strong>int <\/strong>i = 0; i &lt; count; i++)<\/p>\n<p>\u00a0 Liste[i] = cl.Liste[i];<\/p>\n<p>}<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 11<\/p>\n<p>\u00a0<\/p>\n<p>Det interessante ved copy constructoren ses allerede i funktionshovedet. Som enhver anden constructor har den ingen returtype. Derudover skal parametren var const og referenceparameter. Parametertypen skal naturligvis v\u00e6re en instans af klassen &#8211; det er jo h\u00f8jresiden i tildelingen. I eksemplet fra Eksempel 10 vil parametren alts\u00e5 v\u00e6re List1.<\/p>\n<p>\u00a0<\/p>\n<p>Da objekter af samme klasse automatisk er <em>friends<\/em> kan copy contructoren uden videre tilg\u00e5 parametrens private data, s\u00e5som size og count.<\/p>\n<p>\u00a0<\/p>\n<p>Bem\u00e6rk ogs\u00e5, at copy constructoren kun kan tage den ene parameter. Det betyder fx at nedenst\u00e5ende s\u00e6tning ikke er tilladt:<\/p>\n<p>\u00a0<\/p>\n<p>CirkelList List2(5)=List1;<\/p>\n<p>\u00a0<\/p>\n<h2><a name=\"_Toc390869085\">Destructor<\/a><\/h2>\n<p>\u00a0<\/p>\n<p>Det kan n\u00e6sten h\u00f8res af navnet: Destructor er det modsatte af constructor. Destructoren kaldes, n\u00e5r et objekt skal fjernes. Det kan enten skyldes at dets scope er udl\u00f8bet (for lokale variable), eller at objektet er blevet instantieret dynamisk og nu bliver fjernet ved hj\u00e6lp af delete kommandoen. Endeligt kan det ogs\u00e5 skyldes, at programmet er afsluttet.<\/p>\n<p>\u00a0<\/p>\n<p>Da C++ ikke har garbage collection er det op til objekterne selv at frigive den hukommelse, de har allokeret dynamisk. Den hukommelse, der er tildelt statisk &#8211; det vil sige til variable, der ikke er pointere &#8211; bliver automatisk frigivet og skal ikke frigives i destructoren.<\/p>\n<p>\u00a0<\/p>\n<p>Nedenst\u00e5ende er et eksempel p\u00e5 en destructor i klassen CirkelList.<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\"><strong>class <\/strong>CirkelList<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>private:<\/strong><\/p>\n<p>\u00a0\u00a0\u00a0 Cirkel *Liste;<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>size, count; \/\/Max. st\u00f8rrelse og antal indtastede<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0 <strong>public:<\/strong><\/p>\n<p>\u00a0\u00a0\u00a0 \/\/ Constructors<\/p>\n<p>\u00a0\u00a0\u00a0 CirkelList(<strong>int <\/strong>antal=10);<\/p>\n<p>\u00a0\u00a0\u00a0 CirkelList (const CirkelList &amp;cl);<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0 \/\/ Destructor<\/p>\n<p>\u00a0 ~CirkelList ();<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0 \/\/ Operatorer<\/p>\n<p>\u00a0 CirkelList&amp; operator= (CirkelList cl);<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0 \/\/ Andre funktioner<\/p>\n<p>\u00a0 <strong>void <\/strong>Add (Cirkel c); \/\/Tilf\u00f8jer cirkel<\/p>\n<p>};<\/p>\n<p>\u00a0<\/p>\n<p>CirkelList::~CirkelList()<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>if<\/strong> (Liste)<\/p>\n<p>\u00a0 <strong>delete<\/strong>[] Liste;<\/p>\n<p>}<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 12<\/p>\n<p>\u00a0<\/p>\n<p>Ligesom constructoren, har destructoren ingen returtype. Dens navn skal v\u00e6re klassens navn med en tilde (~) foran. Destructoren tager aldrig parametre. I dette eksempel skal den kun frigive det hukommelse, der er tildelt pointeren Liste. F\u00f8rst kontrollerer den dog, at pointeren ikke er null, hvilket kunne v\u00e6re tilf\u00e6ldet, hvis en illegal parameter var overf\u00f8rt til constructoren, eller hvis der ikke havde v\u00e6ret tilstr\u00e6kkelig hukommelse til instantiering.<\/p>\n<p>\u00a0<\/p>\n<p>Bem\u00e6rk i \u00f8vrigt den s\u00e6re notation med de kantede parenteser efter delete. Det angiver, at hele array&#8217;et skal slettes. Var de der ikke, var kun det f\u00f8rste element blevet fjernet.<\/p>\n<p>\u00a0<\/p>\n<h2><a name=\"_Toc390869086\">Kald af funktioner gennem pointere<\/a><\/h2>\n<p>\u00a0<\/p>\n<p>Hvis man har en pointer til et objekt og gerne vil kalde et af objektets funktioner, bruger man i stedet for det vanlige punktum en pil (-&gt;) som scope-angivelse. Se nedenst\u00e5ende eksempel.<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\"><strong>\u00a0 void <\/strong>main()<\/p>\n<p>\u00a0 {<\/p>\n<p>\u00a0\u00a0\u00a0 Cirkel rund(5), rund2;<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0\u00a0\u00a0 CirkelList *List1;<\/p>\n<p>\u00a0\u00a0\u00a0 List1 = <strong>new <\/strong>CirkelList();<\/p>\n<p>\u00a0\u00a0\u00a0 List1-&gt;Add (rund);<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>delete<\/strong> List1;<\/p>\n<p>\u00a0 }<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 13<\/p>\n<p>\u00a0<\/p>\n<p>Bem\u00e6rk, at der f\u00f8rst laves en pointer til et CirkelList-objekt, hvorefter det instantieres ved hj\u00e6lp new. Herefter kaldes funktionen Add med kommandoen List1-&gt;Add(); Slutteligt fjernes objektet med delete. Grunden, til at man er n\u00f8dt til at bruge pilen, er, at man ikke kan dereferenciere objekter. Ellers kunne man jo have klaret sig med kommandoen *List1.Add(rund); Det er <em>ikke <\/em>tilladt.<\/p>\n<h2><a name=\"_Toc390869087\">Templates<\/a><\/h2>\n<p>\u00a0<\/p>\n<p>Ligesom man i C++ kan lave generiske funktioner (template-funktioner) kan man ogs\u00e5 lave template-klasser. I en template-klasse, bygger man klassen til at kunne benytte flere forskellige slags datatyper &#8211; det er herefter op til den enkelte programm\u00f8r at angive i koden, hvilken datatype, der skal benyttes.\u00a0 Hvis vi i stedet for vores CirkelList klasse, ville have en klasse, der bare skulle v\u00e6re en liste, og ellers ikke bekymre sig om, hvad den var en liste af, kunne vi passende g\u00f8re den til en template-klasse. S\u00e5 ville funktionerne komme til at se s\u00e5ledes ud:<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\"><strong>template <\/strong>&lt;<strong>class <\/strong>T&gt;<\/p>\n<p><strong>class <\/strong>List<\/p>\n<p>{<\/p>\n<p><strong>\u00a0 private:<\/strong><\/p>\n<p>\u00a0\u00a0\u00a0 T *Liste;<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>size, count; \/\/Max. st\u00f8rrelse og antal indtastede<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0 <strong>public:<\/strong><\/p>\n<p>\u00a0\u00a0\u00a0 \/\/ Constructors<\/p>\n<p>\u00a0\u00a0\u00a0 List(<strong>int<\/strong> antal=10);<\/p>\n<p>\u00a0\u00a0\u00a0 List(<strong>const <\/strong>List&lt;T&gt; &amp;l);<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0\u00a0\u00a0 \/\/ Destructor<\/p>\n<p>\u00a0\u00a0\u00a0 ~List ();<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0\u00a0\u00a0 \/\/ Operatorer<\/p>\n<p>\u00a0\u00a0\u00a0 List&lt;T&gt;&amp; <strong>operator<\/strong>= (List&lt;T&gt; l);<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0\u00a0\u00a0 \/\/ Andre funktioner<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>void <\/strong>Add (T c); \/\/Tilf\u00f8jer element<\/p>\n<p>};<\/p>\n<p>\u00a0<\/p>\n<p><strong>template <\/strong>&lt;<strong>class <\/strong>T&gt;<\/p>\n<p>List&lt;T&gt;::List (<strong>int<\/strong> Antal)<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>if <\/strong>(Antal &lt; 1)<\/p>\n<p><strong>\u00a0 return<\/strong>;<\/p>\n<p>\u00a0 Liste = <strong>new <\/strong>T[Antal];<\/p>\n<p>\u00a0 count = 0;<\/p>\n<p>}<\/p>\n<p>\u00a0<\/p>\n<p><strong>template <\/strong>&lt;<strong>class <\/strong>T&gt;<\/p>\n<p>List&lt;T&gt;::List (<strong>const <\/strong>List&lt;T&gt; &amp;l)<\/p>\n<p>{<\/p>\n<p>\u00a0 count = l.count;<\/p>\n<p>\u00a0 size = l.size;<\/p>\n<p>\u00a0 Liste = <strong>new <\/strong>T [size];<\/p>\n<p>\u00a0 for (<strong>int <\/strong>i = 0; i &lt; count; i++)<\/p>\n<p>\u00a0 Liste[i] = l.Liste[i];<\/p>\n<p>}<\/p>\n<p>\u00a0<\/p>\n<p><strong>template <\/strong>&lt;<strong>class <\/strong>T&gt;<\/p>\n<p>List&lt;T&gt;::~List()<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>if <\/strong>(Liste)<\/p>\n<p>\u00a0 <strong>delete<\/strong>[] Liste;<\/p>\n<p>}<\/p>\n<p>\u00a0<\/p>\n<p><strong>template <\/strong>&lt;<strong>class <\/strong>T&gt;<\/p>\n<p>List&lt;T&gt;&amp; List&lt;T&gt;::<strong>operator<\/strong>= (List&lt;T&gt; l)<\/p>\n<p>{<\/p>\n<p>\u00a0 size = size &lt; l.size ? size : l.size; \/\/V\u00e6lg mindste st\u00f8rrelse<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0 <strong>for <\/strong>(<strong>int <\/strong>i = 0; i &lt; size; i++)<\/p>\n<p>\u00a0 Liste[i] = l.Liste[i];<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0 <strong>return *this<\/strong>;<\/p>\n<p>}<\/p>\n<p>\u00a0<\/p>\n<p><strong>template <\/strong>&lt;<strong>class <\/strong>T&gt;<\/p>\n<p><strong>void <\/strong>List&lt;T&gt;::Add (T c)<\/p>\n<p>{<\/p>\n<p>\u00a0 Liste[count++] = c;<\/p>\n<p>}<\/p>\n<p>\u00a0<\/p>\n<p><strong>void <\/strong>main()<\/p>\n<p>{<\/p>\n<p>\u00a0 List&lt;<strong>int<\/strong>&gt; IntegerListe (5);<\/p>\n<p>\u00a0 IntegerListe.Add (6);<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0 List&lt;Cirkel&gt; *CirkelListe;<\/p>\n<p>\u00a0 Cirkel rund(5);<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0 CirkelListe = <strong>new <\/strong>List&lt;Cirkel&gt;();<\/p>\n<p>\u00a0 CirkelListe-&gt;Add (rund);<\/p>\n<p>\u00a0 <strong>delete<\/strong> CirkelListe;<\/p>\n<p>}<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 14<\/p>\n<p>\u00a0<\/p>\n<p>Det b\u00e6rende i template-klasser er udtrykket template &lt;class T&gt;, der skrives foran selve klassen og alle medlemsfunktioner. Faktisk er T bare en pladsholder for en hvilken som helst type, og T kan derfor erstattes af et hvilket som helst andet navn.<\/p>\n<p>\u00a0<\/p>\n<p>Da T er pladsholder for den type, der skal bruges i klassen, ser man, at Liste ikke l\u00e6ngere er en pointer til Cirkel, men en pointer til T.\u00a0<\/p>\n<p>\u00a0<\/p>\n<p>Klassens rigtige navn er nu List&lt;<em>type<\/em>&gt;, og da den type vi arbejder med er T, skal den klasse, der skal overf\u00f8res til copy constructoren var List&lt;T&gt;. Det samme g\u00f8r sig g\u00e6ldende i alle funktionshovederne. Her er klasseangivelsen p\u00e5 venstre side af scope-tegnet List&lt;T&gt;. Generelt kan konverteringen af en specifik klasse til en generel template-klasse opdeles i tre punkter:<\/p>\n<p>\u00a0<\/p>\n<ul>\n<li>inds\u00e6t template &lt;class <em>pladsholder<\/em>&gt; foran klassedefinitionen og alle medlemmers funktionshoveder.<\/li>\n<li>erstat referencer til den specifikke type til <em>pladsholder<\/em>.<\/li>\n<li>erstat alle referencer til klassen til klasse&lt;<em>pladsholder<\/em>&gt;.<\/li>\n<\/ul>\n<p>\u00a0<\/p>\n<p>I programmets main-del, ses hvordan listen instantieres. F\u00f8rst laves objektet IntegerList, der er en liste af integers. D\u00e9t angives ved at skrive int i kantede parenteser efter klassenavnet. Det ses nu, at int har taget pladsholderen T&#8217;s plads, og int vil s\u00e5ledes blive indsat alle de steder, der i objektet er referencer til T. Det ses ogs\u00e5, at Add-funktionen, der tager en T som parameter, nu tager en int.<\/p>\n<p>\u00a0<\/p>\n<p>Senere i programmet laves en CirkelListe, der er en liste af typen Cirkel &#8211; den svarer stort set til den CirkelList klasse, der er blevet lavet tidligere. Her vises, hvordan template-klasser allokeres dynamisk &#8211; igen skal man lige huske typen i kantede parenteser &#8211; ellers er systemet det samme.<\/p>\n<p>\u00a0<\/p>\n<h2><a name=\"_Toc390869088\">Nedarvning<\/a><\/h2>\n<p>\u00a0<\/p>\n<p>En af de bedste ting ved objekt-orienteret programmering er muligheden for nedarvning. Her kan man tage det bedste fra en klasse og udvide det med ny kode, for at danne en ny klasse. Vi kan for eksempel lave en Kvadrat-klasse, som vi senere kan nedarve fra for at lave en cirkel-klasse, da en cirkel er et &#8220;kvadrat med runde hj\u00f8rner&#8221;.<\/p>\n<p>\u00a0<\/p>\n<p>Kvadrat-klassen er triviel og ser s\u00e5ledes ud:<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\"><strong>class <\/strong>Kvadrat<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>private:<\/strong><\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>width;<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0 <strong>public:<\/strong><\/p>\n<p><strong>\u00a0\u00a0\u00a0 <\/strong>Kvadrat();<\/p>\n<p>\u00a0\u00a0\u00a0 Kvadrat(<strong>int <\/strong>w);<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>omkreds();<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int<\/strong> areal();<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>getWidth();<\/p>\n<p>};<\/p>\n<p>\u00a0<\/p>\n<p>Kvadrat::Kvadrat()<\/p>\n<p>{<\/p>\n<p>\u00a0 Kvadrat(0);<\/p>\n<p>}<\/p>\n<p>\u00a0<\/p>\n<p>Kvadrat::Kvadrat(<strong>int <\/strong>w)<\/p>\n<p>{<\/p>\n<p>\u00a0 width = w;<\/p>\n<p>}<\/p>\n<p>\u00a0<\/p>\n<p><strong>int <\/strong>Kvadrat::omkreds()<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>return <\/strong>4*width;<\/p>\n<p>}<\/p>\n<p>\u00a0<\/p>\n<p><strong>int <\/strong>Kvadrat::areal()<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>return <\/strong>width*width;<\/p>\n<p>}<\/p>\n<p>\u00a0<\/p>\n<p><strong>int <\/strong>Kvadrat::getWidth()<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>return <\/strong>width;<\/p>\n<p>}<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 15<\/p>\n<p>\u00a0<\/p>\n<p>Den klasse man nedarver fra kaldes en super-klasse, og den klasse, der nedarver kaldes en sub-klasse. Super-klasse og sub-klasse er relative begreber. Det vil sige, at en klasse kan v\u00e6re sub-klasse i forhold til den klasse, den nedarver fra, men den er super-klasse i forhold til de klasse, der nedarver fra den.<\/p>\n<p>\u00a0<\/p>\n<p>Bem\u00e6rk, at super-klassen skal have en default-constructor uden parametre. Denne bliver automatisk kaldt, n\u00e5r der laves instanser af dens sub-klasser. I dette eksempel kalder default-constructoren den rigtige constructor med parameteren 0. I \u00f8vrigt skal det ogs\u00e5 bem\u00e6rkes, at klassens variable ikke er private, men protected. Ligesom private variable, kan protected variable ikke tilg\u00e5s udenfor klassen, men forskellen er, at sub-klasser har adgang til protected data &#8211; det har de ikke til private.<\/p>\n<p>\u00a0<\/p>\n<p>Sub-klasser har automatisk alle super-klassens funktioner. Den kan selv bestemmer, om den vil udvide, erstatte eller beholde disse funktioner. Hvis sub-klassen v\u00e6lger at \u00e6ndre en af super-klassens funktioner, kaldes det <em>overriding<\/em>.<\/p>\n<p>\u00a0<\/p>\n<p>I sub-klassens definition skal kun prototypen p\u00e5 de funktioner, som sub-klassen selv tilf\u00f8jer eller \u00e6ndrer st\u00e5. Da Cirkel-klassen skal \u00e6ndre s\u00e5vel areal som omkreds skal de begge med. Derudover er der naturligvis en constructor. Funktionen getWidth skal ikke \u00e6ndres, og den medtages derfor ikke.<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\"><strong>class <\/strong>Cirkel : <strong>public <\/strong>Kvadrat<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>public:<\/strong><\/p>\n<p>\u00a0\u00a0\u00a0 Cirkel (<strong>int <\/strong>radius);<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>omkreds();<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>areal();<\/p>\n<p>};<\/p>\n<p>\u00a0<\/p>\n<p>Cirkel::Cirkel (<strong>int <\/strong>radius)<\/p>\n<p>{<\/p>\n<p>\u00a0 width = radius;<\/p>\n<p>}<\/p>\n<p>\u00a0<\/p>\n<p><strong>int <\/strong>Cirkel::omkreds()<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>return <\/strong>2*PI*width;<\/p>\n<p>}<\/p>\n<p>\u00a0<\/p>\n<p><strong>int <\/strong>Cirkel::areal()<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>return <\/strong>PI*width*width;<\/p>\n<p>}<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 16<\/p>\n<p>\u00a0<\/p>\n<p>Selve nedarvningen foreg\u00e5r allerede i den f\u00f8rste linie. Efter klassens navn s\u00e6ttes et kolon, hvorefter der skrives public og den klasse, den skal nedarve fra. Herefter har Cirkel-klassen adgang til variablene height og width, der blandt andet bruges i constructoren.<\/p>\n<p>\u00a0<\/p>\n<p>Det blev tidligere n\u00e6vnt, at super-klassen skulle have en default-constructor, der automatisk bliver kaldt. Det foreg\u00e5r i den r\u00e6kkef\u00f8lge, at den \u00f8verste super-klasses contructor kaldes f\u00f8rst, hvorefter constructoren i samtlige sub-klasser kaldes. Den r\u00e6kkef\u00f8lge er ikke tilf\u00e6ldig. Var sub-klassens constructor blevet kaldt f\u00f8rst, ville den havde sat width og height til radius. Herefter ville super-klassens constructor blive kaldt, og width og height ville blive sat til 0.<\/p>\n<p>\u00a0<\/p>\n<p>For at f\u00e5 det p\u00e5 det rene med det samme: destructorerne kaldes i den modsatte r\u00e6kkef\u00f8lge. Det vil sige, at sub-klassens destructor kaldes f\u00f8rst, hvorefter super-klassernes destructorer kaldes.<\/p>\n<p>\u00a0<\/p>\n<h2><a name=\"_Toc390869089\">Polymorfi<\/a><\/h2>\n<p>\u00a0<\/p>\n<p>Man kan sige, at der nu eksisterer to ens funktioner: int areal(). Deres funktionshoved er ens, og det vil s\u00e5ledes ikke v\u00e6re muligt for compileren, at kende forskel p\u00e5 dem &#8211; men der er jo rimelig stor forskel. Heldigvis er det s\u00e5dan, at hvis man har en instans af en sub-klasse, s\u00e5 bliver det sub-klassens funktion, der kaldes. Betragt derimod nedenst\u00e5ende eksempel:<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\"><strong>void <\/strong>main()<\/p>\n<p>{<\/p>\n<p>\u00a0 Kvadrat *k;<\/p>\n<p>\u00a0 k = <strong>new <\/strong>Cirkel(5);<\/p>\n<p>\u00a0 cout &lt;&lt; k-&gt;areal();<\/p>\n<p>}<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 17<\/p>\n<p>\u00a0<\/p>\n<p>Her ses det ikke blot, at det er muligt at s\u00e6tte en pointer til en super-klasse til at pege p\u00e5 en sub-klasse. Eksemplet stiller ogs\u00e5 sp\u00f8rgsm\u00e5let om, hvilken areal-funktion, der kaldes. Umiddelbart, skulle man tro, at det er Cirkel-klassens areal-funktion, der kaldes, men det er ikke tilf\u00e6ldet. Derimod er det Kvadrat-klassens areal-funktion, der bliver udf\u00f8rt. Det skyldes, at det er den eneste funktion, Kvadrat-pointeren kender.<\/p>\n<p>\u00a0<\/p>\n<p>For at undg\u00e5 dette m\u00e5 vi fort\u00e6lle compileren, at hvis sub-klassen selv implementerer en funktion, er det den, der skal udf\u00f8res i stedet. Det g\u00f8res ved at skrive <strong>virtual<\/strong> foran funktionens erkl\u00e6ring. Dette skal k\u00f8res i super-klassen, og ikke i sub-klassen, som jo ellers er den, der har problemet.<\/p>\n<p>\u00a0<\/p>\n<p>I Kvadrat-klassen skulle der alts\u00e5 ikke have st\u00e5et<\/p>\n<p><strong>int<\/strong> areal();<\/p>\n<p>men<\/p>\n<p><strong>virtual <\/strong><strong>int<\/strong> areal();<\/p>\n<p><strong>\u00a0<\/strong><\/p>\n<h2><a name=\"_Toc390869090\">Multipel nedarvning<\/a><\/h2>\n<p>\u00a0<\/p>\n<p>C++ underst\u00f8tter det, der kaldes multipel nedarvning. Det vil sige, at en klasse nedarver fra mere end en klasse. Vi kunne for eksempel forestille os, at Cirkel-klassen ogs\u00e5 nedarver fra en Ellipse-klasse. Ellipse-klassen definition ses i nedenst\u00e5ende eksempel.<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\"><strong>class <\/strong>Ellipse<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>protected<\/strong>:<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>width, height;<\/p>\n<p>\u00a0<\/p>\n<p><strong>\u00a0 public<\/strong>:<\/p>\n<p>\u00a0\u00a0\u00a0 Ellipse();<\/p>\n<p>\u00a0\u00a0\u00a0 Ellipse(<strong>int <\/strong>w, <strong>int <\/strong>h);<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>areal();<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>omkreds();<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>getWidth();<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>getHeight();<\/p>\n<p>};<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 18<\/p>\n<p>\u00a0<\/p>\n<p>Hvis Cirkel-klassen skal nedarve fra s\u00e5vel Kvadrat-klassen som Ellipse-klassen, tilf\u00f8jes &#8220;, public Ellipse&#8221; til nedarvningslinien.<\/p>\n<p>\u00a0<\/p>\n<p>Hvis koden nu fors\u00f8ges kompileret, f\u00e5r man imidlertid en fejlmeddelelse, n\u00e5r man pr\u00f8ver at tilg\u00e5 variablen width i Cirkel-klassen: &#8220;Member is ambiguous.&#8221; Det skyldes at compileren ikke kan kende forskel p\u00e5 width fra Kvadrat-klassen og width fra Ellipse-klassen. Det samme g\u00e6lder referencer til funktionen getWidth().<\/p>\n<p>\u00a0<\/p>\n<p>Problemet kan klares ved at angive scope foran henvisningerne. S\u00e5 kommer constructoren for eksempel til at se s\u00e5ledes ud:<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\">Cirkel::Cirkel (<strong>int <\/strong>radius)<\/p>\n<p>{<\/p>\n<p>\u00a0 Kvadrat::width = radius;<\/p>\n<p>}<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 19<\/p>\n<p>\u00a0<\/p>\n<p>Det samme kan g\u00f8res i funktionskaldet til getWidth(). S\u00e5 kommer det til at se s\u00e5ledes ud:<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\"><strong>void <\/strong>main()<\/p>\n<p>{<\/p>\n<p>\u00a0 Cirkel c(5);<\/p>\n<p>\u00a0 cout &lt;&lt; c.omkreds() &lt;&lt; endl &lt;&lt; c.Kvadrat::getWidth();<\/p>\n<p>}<\/p>\n<p>\u00a0<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 20<\/p>\n<p>\u00a0<\/p>\n<p>P\u00e6nt er det ikke, men det virker.<\/p>\n<p>\u00a0<\/p>\n<h2><a name=\"_Toc390869091\">Virtuelle nedarvning<\/a><\/h2>\n<p>\u00a0<\/p>\n<p>Multipel nedarvning giver i midlertid ogs\u00e5 et andet problem. Hvis klassen A er super-klasse for b\u00e5de klasserne B og C, og D nedarver fra s\u00e5vel B og C, vil funktionerne i A blive nedarvet to gange. Nedenst\u00e5ende klassediagram viser nedarvningerne.<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<p>Lad os antage, at klasen A har en protected variabel test. B har en funktion setTest, der l\u00e6gger en v\u00e6rdi i variable test. C har en funktion getTest, der returnerer v\u00e6rdien af test-variablen, mens D bare har funktionen run, der starter eksemplet. C++ koden til de fire klasser ser s\u00e5ledes ud:<\/p>\n<p>\u00a0<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\"><strong>class <\/strong>A<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>protected:<\/strong><\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>test;<\/p>\n<p>};<\/p>\n<p>\u00a0<\/p>\n<p><strong>class<\/strong> B : <strong>public <\/strong>A<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>public:<\/strong><\/p>\n<p>\u00a0\u00a0\u00a0 <strong>void<\/strong> setTest(<strong>int <\/strong>t)<\/p>\n<p>\u00a0\u00a0\u00a0 {<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0 test = t;<\/p>\n<p>\u00a0\u00a0\u00a0 }<\/p>\n<p>};<\/p>\n<p>\u00a0<\/p>\n<p><strong>class <\/strong>C : <strong>public <\/strong>A<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>public:<\/strong><\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>getTest()<\/p>\n<p>\u00a0\u00a0\u00a0 {<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0 <strong>return <\/strong>test;<\/p>\n<p>\u00a0\u00a0\u00a0 }<\/p>\n<p>};<\/p>\n<p>\u00a0<\/p>\n<p><strong>class <\/strong>D : <strong>public <\/strong>B, <strong>public <\/strong>C<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>public:<\/strong><\/p>\n<p>\u00a0\u00a0\u00a0 <strong>void <\/strong>run()<\/p>\n<p>\u00a0\u00a0\u00a0 {<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0 setTest (5);<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0 cout &lt;&lt; getTest();<\/p>\n<p>\u00a0\u00a0\u00a0 }<\/p>\n<p>};<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 21<\/p>\n<p>\u00a0<\/p>\n<p>Man skulle tro, at udskriften ville vise 5, men den viser faktisk 8394 eller et eller andet andet tilf\u00e6ldigt tal. Det skyldes, at variablen test bliver nedarvet to gange: b\u00e5de gennem B og gennem C. N\u00e5r funktionen setTest i B bliver kaldt, s\u00e6tter den sit eksemplar af test til 5, mens C&#8217;s getTest-funktion returnerer v\u00e6rdien af sin egen test, og den er u\u00e6ndret.<\/p>\n<p>\u00a0<\/p>\n<p>For at undg\u00e5r dette m\u00e5 man bruge virtuel nedarvning. Her s\u00f8rger compileren for, at kun en version af hver variabel og funktion nedarves. I C++ laver man virtuel nedarvning ved at bruge det reserverede ord virtual.<\/p>\n<p>\u00a0<\/p>\n<p>Virtual nedarvning foretages ved at skrive <strong>virtual <\/strong>foran de klasser, der nedarves fra. Bem\u00e6rk at dette <em>ikke<\/em> har noget som helst med virtuelle funktioner at g\u00f8re (ud over, at det er det samme reserverede ord, man bruger).<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\"><strong>class <\/strong>A<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>protected<\/strong>:<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>test;<\/p>\n<p>};<\/p>\n<p>\u00a0<\/p>\n<p><strong>class <\/strong>B : <strong>virtual public <\/strong>A<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>public<\/strong>:<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>void<\/strong> setTest(<strong>int <\/strong>t)<\/p>\n<p>\u00a0\u00a0\u00a0 {<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0 test = t;<\/p>\n<p>\u00a0\u00a0\u00a0 }<\/p>\n<p>};<\/p>\n<p>\u00a0<\/p>\n<p><strong>class <\/strong>C : <strong>virtual public <\/strong>A<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>public<\/strong>:<\/p>\n<p>\u00a0\u00a0\u00a0 <strong>int <\/strong>getTest()<\/p>\n<p>\u00a0\u00a0\u00a0 {<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0 <strong>return <\/strong>test;<\/p>\n<p>\u00a0\u00a0\u00a0 }<\/p>\n<p>};<\/p>\n<p>\u00a0<\/p>\n<p><strong>class <\/strong>D : <strong>public <\/strong>B, <strong>public <\/strong>C<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>public:<\/strong><\/p>\n<p>\u00a0\u00a0\u00a0 void run()<\/p>\n<p>\u00a0\u00a0\u00a0 {<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0 setTest (5);<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0 cout &lt;&lt; getTest();<\/p>\n<p>\u00a0\u00a0\u00a0 }<\/p>\n<p>};<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 22<\/p>\n<p>\u00a0<\/p>\n<h2><a name=\"_Toc390869092\">Abstrakte klasser<\/a><\/h2>\n<p>\u00a0<\/p>\n<p>N\u00e5r man laver en super-klasse, kan man komme ud for, at de klasser, der nedarver fra den, godt nok har en funktion, der hedder det samme og g\u00f8r nogenlunde det samme, men alligevel kan de ikke bruge den samme kode &#8211; funktionen skal simpelthen skrives for hver enkelt sub-klasse.<\/p>\n<p>\u00a0<\/p>\n<p>Da funktionsnavnet findes i alle sub-klasserne, vil det v\u00e6re naturligt, at det ogs\u00e5 findes i super-klassen. S\u00e5 vil der imidlertid komme det problem, at hvis en eller anden laver en instans af superklassen og pr\u00f8ver at kalde den p\u00e5g\u00e6ldende funktion, sker der ikke noget.\u00a0 Derfor kan man erkl\u00e6re en funktion pure virtual. Det angiver, at der i den klasse ikke findes kode til den funktion. Klasser, der indeholder bare en pure virtual funktion, kaldes abstrakte klasser, og dem er det ikke muligt at lave objekter af.<\/p>\n<p>\u00a0<\/p>\n<p>Hvis en klasse arver fra en abstrakt klasse, skal den selv implementere de pure virtuelle funktioner. G\u00f8r den ikke det, bliver den selv en abstrakt klasse.<\/p>\n<p>\u00a0<\/p>\n<p>En funktion erkl\u00e6res pure virtual ved at skrive virtual foran den og = 0 efter den. Det fremg\u00e5r af eksempel 23.<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\"><strong>class <\/strong>A<\/p>\n<p>{<\/p>\n<p>\u00a0 <strong>virtual void <\/strong>b() = 0;<\/p>\n<p>};<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 23<\/p>\n<p>\u00a0<\/p>\n<h2><a name=\"_Toc390869093\">Statiske funktioner<\/a><\/h2>\n<p>\u00a0<\/p>\n<p>Normalt skal der jo oprettes en instans (et objekt) af en klasse, f\u00f8r dens funktioner kan kaldes. Man kan imidlertid lave statiske funktioner. Disse kan kaldes blot ved at angive klassen. S\u00e5ledes ved <strong>MyClass::f() <\/strong>kalde den statiske funktion f() i klassen MyClass.<\/p>\n<p>\u00a0<\/p>\n<p>Eksempel 24 viser, hvordan statiske funktioner erkl\u00e6res. Det skal bem\u00e6rkes, at statiske funktioner kun m\u00e5 kalde funktioner, der ogs\u00e5 er statiske. Ligeledes skal alle variable, der bruges af en statisk funktion, v\u00e6re statiske.<\/p>\n<p>\u00a0<\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"568\" valign=\"top\"><strong>class <\/strong>MyClass<\/p>\n<p>{<\/p>\n<p><strong>\u00a0 private:<\/strong><\/p>\n<p><strong>\u00a0\u00a0\u00a0 static int <\/strong>x;<\/p>\n<p><strong>\u00a0 public:<\/strong><\/p>\n<p><strong>\u00a0\u00a0\u00a0 static void <\/strong>f();<\/p>\n<p>};<\/p>\n<p>\u00a0<\/p>\n<p><strong>int <\/strong>MyClass::x = 0;<\/p>\n<p>\u00a0<\/p>\n<p><strong>void <\/strong>MyClass::f()<\/p>\n<p>{<\/p>\n<p>\u00a0 x*=2;<\/p>\n<p>}<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Eksempel 24<\/p>\n<p>\u00a0<\/p>\n<p>Af eksemplet ses det ogs\u00e5, hvordan statiske funktioner initialiseres. Det g\u00f8res ved f\u00f8lgende syntaks: <em>type klasse<\/em>::<em>variabel<\/em> = <em>v\u00e6rdi<\/em>;<\/p>\n<p>\u00a0<\/p>\n<hr size=\"1\" \/><a name=\"_ftn1\" href=\"http:\/\/www.kristiansborg.dk\/bibliotek\/wp-includes\/js\/tinymce\/plugins\/paste\/blank.htm#_ftnref1\">[1]<\/a> Man kan faktisk bruge teknikken til at definere flere forskellige typer af alle slags funktioner, men her ser vi kun p\u00e5 mulighederne for multiple constructors.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Indhold Indledning&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;.. 2 Hvordan en klasse erkl\u00e6res&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230; 2 Angivelse af funktioner&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;. 3 Constructor&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230; 3 Erkl\u00e6ring af et objekt&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230; 4 Requests (kald af medlemsfunktioner)&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230; 5 Konstante objekter&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230; 5 Multiple constructors&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;. 6 Alternativ assignment-metode i constructors&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230; 7 Operator overloading&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230; 7 Friend-funktioner&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;. 11 Dynamisk instantiering af objekter&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;. 12 Copy constructor&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;. 13 Destructor&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230; 14 Kald af funktioner gennem pointere&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;.. [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":13,"menu_order":0,"comment_status":"closed","ping_status":"open","template":"","meta":{"_monsterinsights_skip_tracking":false,"footnotes":""},"class_list":["post-14","page","type-page","status-publish","hentry"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.0.1 - aioseo.com -->\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/objektorienteret-programmering-i-c\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.0.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"da_DK\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Biblioteket | Samling af artikler og b\u00f8ger\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Objektorienteret programmering i C++ | Biblioteket\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/objektorienteret-programmering-i-c\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2008-10-16T08:22:09+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2008-10-16T08:22:09+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Objektorienteret programmering i C++ | Biblioteket\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/objektorienteret-programmering-i-c\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/#listItem\",\"name\":\"B\\u00f8ger\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/#listItem\",\"position\":2,\"name\":\"B\\u00f8ger\",\"item\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/objektorienteret-programmering-i-c\\\/#listItem\",\"name\":\"Objektorienteret programmering i C++\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/objektorienteret-programmering-i-c\\\/#listItem\",\"position\":3,\"name\":\"Objektorienteret programmering i C++\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/#listItem\",\"name\":\"B\\u00f8ger\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/#organization\",\"name\":\"Biblioteket\",\"description\":\"Samling af artikler og b\\u00f8ger\",\"url\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/objektorienteret-programmering-i-c\\\/#webpage\",\"url\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/objektorienteret-programmering-i-c\\\/\",\"name\":\"Objektorienteret programmering i C++ | Biblioteket\",\"inLanguage\":\"da-DK\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/b%c3%b8ger\\\/objektorienteret-programmering-i-c\\\/#breadcrumblist\"},\"datePublished\":\"2008-10-16T10:22:09+02:00\",\"dateModified\":\"2008-10-16T10:22:09+02:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/#website\",\"url\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/\",\"name\":\"Biblioteket\",\"description\":\"Samling af artikler og b\\u00f8ger\",\"inLanguage\":\"da-DK\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.kristiansborg.dk\\\/bibliotek\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Objektorienteret programmering i C++ | Biblioteket","description":"","canonical_url":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/objektorienteret-programmering-i-c\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BreadcrumbList","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/objektorienteret-programmering-i-c\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek#listItem","position":1,"name":"Home","item":"https:\/\/www.kristiansborg.dk\/bibliotek","nextItem":{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/#listItem","name":"B\u00f8ger"}},{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/#listItem","position":2,"name":"B\u00f8ger","item":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/","nextItem":{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/objektorienteret-programmering-i-c\/#listItem","name":"Objektorienteret programmering i C++"},"previousItem":{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/objektorienteret-programmering-i-c\/#listItem","position":3,"name":"Objektorienteret programmering i C++","previousItem":{"@type":"ListItem","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/#listItem","name":"B\u00f8ger"}}]},{"@type":"Organization","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/#organization","name":"Biblioteket","description":"Samling af artikler og b\u00f8ger","url":"https:\/\/www.kristiansborg.dk\/bibliotek\/"},{"@type":"WebPage","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/objektorienteret-programmering-i-c\/#webpage","url":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/objektorienteret-programmering-i-c\/","name":"Objektorienteret programmering i C++ | Biblioteket","inLanguage":"da-DK","isPartOf":{"@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/#website"},"breadcrumb":{"@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/objektorienteret-programmering-i-c\/#breadcrumblist"},"datePublished":"2008-10-16T10:22:09+02:00","dateModified":"2008-10-16T10:22:09+02:00"},{"@type":"WebSite","@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/#website","url":"https:\/\/www.kristiansborg.dk\/bibliotek\/","name":"Biblioteket","description":"Samling af artikler og b\u00f8ger","inLanguage":"da-DK","publisher":{"@id":"https:\/\/www.kristiansborg.dk\/bibliotek\/#organization"}}]},"og:locale":"da_DK","og:site_name":"Biblioteket | Samling af artikler og b\u00f8ger","og:type":"article","og:title":"Objektorienteret programmering i C++ | Biblioteket","og:url":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/objektorienteret-programmering-i-c\/","article:published_time":"2008-10-16T08:22:09+00:00","article:modified_time":"2008-10-16T08:22:09+00:00","twitter:card":"summary","twitter:title":"Objektorienteret programmering i C++ | Biblioteket"},"aioseo_meta_data":{"post_id":"14","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"location":null,"local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"ai":null,"created":"2020-12-21 06:59:33","updated":"2025-06-04 00:30:15","seo_analyzer_scan_date":null,"focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.kristiansborg.dk\/bibliotek\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/\" title=\"B\u00f8ger\">B\u00f8ger<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tObjektorienteret programmering i C++\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/www.kristiansborg.dk\/bibliotek"},{"label":"B\u00f8ger","link":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/"},{"label":"Objektorienteret programmering i C++","link":"https:\/\/www.kristiansborg.dk\/bibliotek\/b%c3%b8ger\/objektorienteret-programmering-i-c\/"}],"_links":{"self":[{"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/pages\/14","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/comments?post=14"}],"version-history":[{"count":0,"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/pages\/14\/revisions"}],"up":[{"embeddable":true,"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/pages\/13"}],"wp:attachment":[{"href":"https:\/\/www.kristiansborg.dk\/bibliotek\/wp-json\/wp\/v2\/media?parent=14"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}