• No results found

Undvik pekare

N/A
N/A
Protected

Academic year: 2021

Share "Undvik pekare"

Copied!
40
0
0

Loading.... (view fulltext now)

Full text

(1)

Lokala objekt allokeras på stacken och har kort livslängd

• Objekt med längre livslängd måste

allokeras dynamiskt på heapen (free store)

Dynamisk allokering görs med new och delete

• Statiska och globala objekt finns under programmets hela körtid

Minneshantering

(2)

Minne (objekt) som allokerats med new ska deallokeras med delete

Minne (vektorer av objekt) som allokerats med new[] ska deallokeras med delete[]

void foo() {

A a; // a allokerad på stacken A *ap = new A; // dynamiskt allokerad A *aa = new A[5]; // vektor med 5 A-objekt delete ap; // frigör allokerat minne

delete aa; // fel: odefinierat beteende!

delete [] aa; // ok: destruktor för 5 element } /* vid funktionens slut frigörs a automatiskt */

Minneshantering

(3)

• C++ har ingen automatrisk

minneshantering (garbage collection)

• Alla dynamiska objekt som inte lämnas tillbaka läcker minne

• Speciellt viktigt är det att hålla ordning på minnet i objekt som skapas och destrueras ofta som t.ex. strängar.

Minneshantering

(4)

• Undvik pekare!

Det är lätt att referera otillåtet minne (t.ex.

genom att avreferera NULL)

Det är lätt att referera ogiltigt minne (redan frigjort med delete)

• Skapa istället objekt på stacken

• Använd referenser! Dessa är garanterade att alltid referera ett giltigt objekt

Undvik pekare

(5)

Exempel på hur referenser och pekare används som alias för ett objekt

class A { public: int i; };

A a; // objekt

A &arf; // fel: arf måste initieras A &ar = a; // ok: ar refererar a

int i;

i = a.i; // vi kommer åt a.i genom a i = ar.i; // ar används istället för a

void foo(const A &); // deklaration

foo(a); // skicka a som referens

Referenser

(6)

• Körs innan programmet ses av kompilatorn

• Används för att inkludera/exkludera källkod

• Kan användas för att definiera konstanter och makron

• C++ har många tekniker för att undvika

preprocessorn, såsom inline, template och const

Preprocessor

(7)

#include <iostream> // inkluderar filen iostream #include "myfile.h" // letar i lokal katalog först

#ifdef MSDOS // inkludera endast om MSDOS-miljö #include <conio.h>

#endif

Preprocessor

(8)

Klasser Klasser

Medlemmar Åtkomst

Statiska variabler

(9)

Klasser

Klasser används för att

• strukturera koden

• kapsla in data

• knyta metoder till data

• skapa återanvändbara komponenter

(10)

Medlemmar och åtkomst

Alla kommer åt public

Endast subklasser kommer åt protected

Endast klassen själv kommer åt private

(11)

Medlemmar och åtkomst

c l a s s A c c o u n t {

p u b l i c : / / t i l l g ä n g l i g a f ö r a l l a v o i d d e p o s i t ( d o u b l e d ) { b a l a n c e + = d ; } v o i d w i t h d r a w ( d o u b l e d ) { b a l a n c e - = d ; }

p r o t e c t e d :

d o u b l e b a l a n c e ; / / e n d a s t t i l l g ä n g l i g i k l a s s e n } ;

/ / g l ö m i n t e s e m i k o l o n !

i n t m a i n ( ) {

A c c o u n t s a v i n g s ;

s a v i n g s . d e p o s i t ( 1 0 ) ; s a v i n g s . w i t h d r a w ( 3 . 5 0 ) ; r e t u r n 0 ;

}

(12)

/ * m y f i l e . h - - h e a d e r f i l m e d d e k l a r a t i o n e r * / c l a s s A

{

i n t i ; / / i ä r p r i v a t e p u b l i c : / / f o o ä r i n l i n e i n t f o o ( c h a r ) { r e t u r n 7 ; }

i n t b a r ( ) ; / / b a r , b a z ä r i n l i n e o m c h a r b a z ( ) ; / / d e f i n i t i o n e n a n g e r d e t p r o t e c t e d :

d o u b l e d ; } ;

i n l i n e i n t A : : b a r ( ) { r e t u r n 2 ; } / / i n l i n e i . h - f i l

/ * m y f i l e . c p p - - k ä l l k o d s f i l m e d d e f i n i t i o n e r * /

c h a r A : : b a z ( ) { r e t u r n ' x ' ; } / / e j i n l i n e i . c p p - f i l

Medlemmar och åtkomst

Medlemsfunktioner som definieras i klass- deklarationen blir inline

(13)

Statiska medlemmar

• Statiska medlemmar är gemensamma för alla instanser av samma klass

• De kan t.ex. användas till att räkna instanser av klassen

(14)

class A { // i headerfil myfile.h

static const int size = 4711; // statisk medlem static int cnt; // statisk medlem int array[size]; // vanlig medlem public:

static int count() {return cnt;} // statisk funktion };

// i implementationsfil myfile.cpp

const int A::size; // statiska medl. måste definieras int A::cnt; // ... och defaultvärde är 0

...

int i = A::count();

Statiska medlemmar

(15)

Konstruktion och destruktion Konstruktion och destruktion

Konstruktorer

Implicita konstruktorer Initieringslistan

Destruktorer

(16)

Konstruktorer

När ett objekt instansieras anropas dess konstruktor

Konstruktorn saknar returtyp

En implicit konstruktor tillhandahålls av

kompilatorn ”vid behov” och kör konstruktorn på alla objekt i klassen

Konstruktorn utan argument kallas

defaultkonstruktor och anropas vid konstruktion utan argument

(17)

Konstruktorer

Konstruktorn har samma namn som klassen

Konstruktorns jobb är att initiera objektet

class A {

public:

A() // konstruktor {

i = 0; // konstruktorns kropp }

protected:

int i;

};

(18)

• Vissa typer kan inte tilldelas, bara initieras

• Tilldelning är onödigt arbete om objktet istället kan initieras till rätt värde

• Använd initieringslistan för initiering av allt data i klassen

Initiera pekare till NULL och allokera eventuellt dynamiskt minne i kroppen

Konstruktorer och initieringslistan

(19)

Konstruktorer och initieringslistan

class A {

public:

A(int &v) // konstruktor

: p(0), ref(v), str("hello") // initieringslista {} // tom kropp

protected:

int *p;

int &ref;

std::string str;

};

(20)

Konstruktorer kan överlagras

Använd explicit då konstruktorn har ett

argument av enkel typ för att undvika ofrivillig konvertering

Konstruktorer

(21)

Konstruktorer

// date.h -- headerfil class Date

{

public:

Date(const Date &); // kopieringskonstruktor Date(int y, int m, int d); // ÅÅMMDD

explicit Date(int c); // dagar från 1900-01-01 ...

int year, month, date;

};

// date.cpp -- källkodsfil

Date::Date(const Date &d) { /* kopiering */ } Date::Date(int y, int m, int d)

: year(y), month(m), date(d) // initiering av medl.

{ }

Exempel på överlagrad konstruktor och explicit

(22)

Konstruktorer

Lite överkurs:

Konstruktor som är protected ger klass som bara kan skapas av subklasser

Konstruktor som är private ger möjlighet att förhindra användandet av t.ex. kopierings-

konstruktorn

(23)

Konstruktorer

Kopieringskonstruktorn och tilldelningsoperatorn är privata

De saknar definition, så om de används (kan endast ske i OS pga private) så får man länkarfel

class OS // Operating System {

public:

OS() {} // konstruktor ...

private:

OS(const OS &); // ingen definition const OS &operator=(const OS &);

};

(24)

När ett objekt förstörs (t.ex. med delete eller då det hamnar utom räckvidd) anropas dess

destruktor

Destruktorn i en basklass bör vara deklarerad virtual

Destruktorn har ingen returtyp och tar inga argument

Syntaxen för destruktorn ~A() kommer från operatorn för bitvis komplement (~), dvs icke

Destruktorn

(25)

// ligger i string.h -- headerfil class String {

public:

String() : str(0) {} // defaultkonstruktor String(const char *s); // kopierar s

~String(); // destruktor protected:

char *str;

};

// ligger i string.cpp -- källkodsfil String::String(const char *s) : str(0) {

str = new char[strlen(s) + 1]; // glöm inte '\0' strcpy(str, s);

}

String::~String() { delete [] str; } // obs! delete[]

Destruktorn

(26)

this -pekaren

• I en medlemsfunktion kan man komma åt objektet genom att använda den

fördefinierade pekaren this

this går inte att tilldela

(27)

class MyInt {

int i;

public:

MyInt &increase(int);

};

inline MyInt &MyInt::increase(int j) {

i += j;

return *this; // ger referens till objektetet självt }

this -pekaren

(28)

Arv Arv

Arv

Aggregation Åtkomst Multipelt arv

Virtuella basklasser

(29)

Arv och aggregation

Återanvändning kan ske genom:

Aggregat (innehållande), ”har en”

Arv, ”är en”

class Animal {

// Animal innehåller (har en) sträng std::string species;

};

// Bear ärver (är en) Animal class Bear : public Animal {

...

};

(30)

Arv och konstruktorer

• I en arvskedja måste basklasserna initieras före objektets kropp körs

• Annars skulle man kunna använda

oinitierade referenser och konstanter som ligger i basklassen

• Basklassens konstruktor körs alltid först i initieringslistan

• Anges inget anrop till basklass anropas dess defaultkonstruktor

(31)

Antag arvshierarki A  B C och skapandet av ett objekt av typen C

Exekveringsordningen blir:

Initieringslistan för C anropar initieringslistan för B som anropar initieringslistan för A

Initieringslistan för A utförs Kroppen för A utförs

Initieringslistan för B utförs Kroppen för B utförs

Initieringslistan för C utförs Kroppen för C utförs

Arv och konstruktorer

(32)

class Vehicle {

public:

Vehicle(int w) : weight(w) {}

int weight;

};

class Car : public Vehicle {

public:

Car(int p, int w) : Vehicle(w), persons(p) {}

int persons;

};

...

Car volvo(5, 1700);

int i = volvo.weight;

Arv och konstruktorer

(33)

Olika typer av arv: public, protected och private

Arv och åtkomst

arv

funktion public protected private

public public protected private

protected protected protected private

private

(34)

Åtkomst vid arv

• Klasser som är till hjälp för implemen- tationen bör ärvas private

• Man vill inte ha implementationsdetaljer i sitt gränssnitt

(35)

Multipelt arv

C++ stöder multipelt arv av godtyckligt antal klasser.

class Boat {

public:

Boat(bool s) : has_sail(s) {}

bool has_sail;

};

class Amphibian : public Car, public Boat {

public:

Amphibian(int pers, int wt, bool sail = false) : Car(pers, wt), Boat(sail) {}

};

(36)

Virtuell basklass

För att använda gemensamt data i en delad basklass använder man virtuella basklasser genom nyckelordet virtual.

Av

Bv Cv

Dv A

A

B C

D

Vanligt arv

Vanligt arv Virtuellt arvVirtuellt arv

(37)

class A { public: int i; };

class B : public A {};

class C : public A {};

class D : public B, public C {};

class Bv : virtual public A {};

class Cv : virtual public A {};

class Dv : public Bv, public Cv {};

Dv dv;

dv.A::i = 7; // alla ändrar samma data dv.Bv::i = 8;

dv.Cv::i = 9;

D d;

d.A::i = 7; // fel: tvetydigt

d.B::i = 8; // ok: ändrar D->B->A1 d.C::i = 9; // oj, ändrar D->C->A2

Ett exempel på hur data kan delas mellan basklasserna:

Virtuell basklass

(38)

const

Deklarationer med const ger skrivskydd.

class A {

const int ci; // ci är skrivskyddad (ssk) const int *p_ci; // pekare till ssk int

int *const cp_i; // ssk pekare till int

const int *const cp_ci; // ssk pekare till ssk int

int get() const; // objektet är ssk i get int i;

};

// källkodsfil

int A::get() const { return i; } // ok: ändrar inte int A::get() const { return i = 2; } // fel: ändrar obj

(39)

const och this

this-pekaren går inte att tilldela, dvs pekaren går inte att flytta eftersom den är skrivskyddad

Pekaren är ”deklarerad”

T *const this;

då funktionen inte är const

Pekaren är ”deklarerad”

const T *const this;

då funktionen är const

(40)

const och mutable

Funktioner deklarerade med const gör objektet read-only. Med mutable inför man ett undantag.

class A {

int get() const; // objektet är read-only i get int i;

mutable int access_count;

};

inline

int A::get() const {

access_count++; // ok: får ändras trots const return i;

}

References

Related documents

UNDVIK RÖRA VID ÖGON, NÄSA ELLER MUN. AVOID TOUCHING YOUR EYES, NOSE

Enligt huvudregeln skulle det alltså heta Varför vill (s) driva Britta från hennes hus?, eftersom vi inte avser att syfta på subjektet (som i den här meningen är (s)).. Den

Detta skulle enligt den objektivistiska pluralistiska teorin innebära en högre livskvalitet för dessa mödrar där verksamheter, så som ett arbete, har ett finalt värde för en

Kostnadsfritt stöd för dig som är vuxen och anhörig till en person med psykisk eller fysisk funktionsnedsättning, till äldre eller en person som är långvarigt sjuk.

I detta fall gör då inte kravet är att det övertagande bolaget ska vara skattskyldigt för sådan verksamhet som det överlåtande bolaget beskattats för innan fusionen vilket

Var noga med att undvika trängsel och hålla avstånd till andra på platser där många samlas, till exempel i butiker, köpcentrum, restauranger, uteserveringar och på

För alla numeriska värden som inte är flyttal finns även en metod för konvertering till någon av baserna 2, 8, 10 eller 16.. Det enda undantagsfel som kan inträffa

Sjuksköterskors attityder till och upplevelser av att samtala kring sexualitet med patienter inom onkologisk vård var bland annat att sjuksköterskor ansåg att sexualitet var