• No results found

Synlighet Synlighet

N/A
N/A
Protected

Academic year: 2021

Share "Synlighet Synlighet"

Copied!
24
0
0

Loading.... (view fulltext now)

Full text

(1)

Synlighet Synlighet

Namespace

Scope-operatorn Klasser

Vänner

(2)

Synlighet

• Ett problem med moduler i C är att alla

variabel- och funktionsnamn ligger globalt synliga.

• C++ botar detta genom att införa det mycket användbara nyckelordet namespace

I namnrymder kan man kapsla in klasser, funktioner och data

Med synlighetsoperatorn (scope operator) ::

kan man komma åt en namnrymd och medlemmar i klasser

(3)

Med using exponerar man innehåll i en namnrymd

Med odöpta namnrymder (unnamed

namespaces) kan man deklarera data som endast är synliga i filen där de är definierade

• ObsoIet metod: I C (och därför även C++) skapar man filstatiska funktioner genom nyckelordet static

• Genom att ha fillokala data minskar risken för namnkonflikter

Synlighet

(4)

Synlighet

namespace Spc // håll namnen på namnrymder korta {

class A; // framåt(forward)deklaration int foo();

int j;

enum {arms = 2, legs = 1, hair = 517};

}

class Spc::A // A är inte synlig utan Spc::

{

public :

int foo();

int j;

};

inline int Spc::A::foo() {return j;} // använder Spc::A::j inline int Spc::foo() {return j;} // ok: Spc::j synlig

(5)

Synlighet

int main() {

if(Spc::j > Spc::legs) // Använd Spc::j och { /*...*/ } // Spc::legs explicit

using Spc::j; // j synlig i hela main()

j = Spc::foo(); // foo() ej synlig, använd Spc::

Spc::A a;

j = a.foo(); // Spc::A::foo() synlig genom a

using Spc::A; // hela klassen A synlig using namespace Spc; // allt data i Spc synligt

return 0;

}

(6)

Några överkursexempel på namnrymder och using

na m es pa c e XY Z _v e rs io n 1 {

i nt i ;

v oi d f o o( ) ; // d e kl ar a ti on }

na m es pa c e XY Z _v e rs io n 2 {

i nt i ; i nt j ;

v oi d f o o( ) ; // d e kl ar a ti on }

na m es pa c e XY Z = XY Z_ v er si o n2 ; // a l ia s f ör n a mn r ym d

vo i d XY Z :: fo o () {} // d e fi ni t io n a v XY Z _v er 2 :: f oo in t i ; // g l ob al va ri a be l i

in t j ; // g l ob al va ri a be l j

// ex em p el p å u s in gd e kl ar a ti on (e ns t ak a v ar ia b el ) {

u si n g XY Z :: i ; // l o ka l i , gö m me r g lo b al i i = 3; // o k : lo k al i

}

// ex em p el p å u s in gd i re kt i v (h e l na m nr ym d ) {

u si n g na m es p ac e X YZ ; // i n tr od u ce ra r i , j o c h fo o j = 4; // f e l! : : j el l er X Y Z: : j ? }

(7)

Man kan byta synlighet på medlemmar med using

Synlighet

struct A { protected:

int i;

};

struct B : public A { using A::i;

};

A a;

B b;

a.i = 1; // fel: i är protected b.i = 2; // ok

(8)

Synlighet och klasser

• För att komma åt data i klasser använder man synlighetsoperatorn ::

• Ett bra exempel på hur synlighetsoperatorn används är STLs iteratorer

• Iteratorerna är inkapslade i behållarklasserna och döpta till samma sak: T::iterator

resp. T::const_iterator

(9)

Synlighet och klasser

// här kan vi byta till lämpligare behållare vid behov // t.ex. std::vector eller std::deque

typedef std::list<std::string> T;

T t;

...

// oavsett klass, hämta dess const_iterator T::const_iterator i = t.begin();

for(; i != t.end(); ++i)

std::cout << *i << std::endl;

Nedanstående exempel visar hur man kan använda klassens synlighetoperator för att abstrahera sin kod

(10)

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

(11)

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;

}

(12)

Vänner

• Ibland måste en klass ha tillgång till data i en annan

• Man vill dock inte använda åtkomsttypen public eftersom man får oönskad insyn

• Man specificerar sina vänner (klass eller funktion) med friend

De får då åtkomstnivå public på data och funktioner

friend-förhållandet ärvs inte

friend bör undvikas för att inte äventyra inkapslingen

(13)

cl a ss M y In t {

i nt i; // i är p r iv a te pu b li c:

M yI n t( in t j ) : i ( j) { }

f ri e nd c o ns t M yI n t op e ra to r *( in t , co n st M y In t & );

f ri e nd s t d: : os tr e am &

o pe r at or < <( s td :: o st re a m &, co ns t M yI n t &) ; };

in l in e c on st My I nt o p er at o r* (i n t i, co ns t M yI n t & j)

{ r et ur n M yI n t( i * j . i) ; } // k o mm er åt My In t :: i

in l in e s td :: o st r ea m &

op e ra to r << (s t d: : os tr e am & s , co n st M y In t & j)

{ s < < " {M yI n t = " < < j .i << " } "; } // k o mm er åt My In t :: i

Vänner

(14)

Överlagring av operatorer Överlagring av operatorer

Konstanta referenser Returtyper

Argumenttyper

(15)

Överlagring av operatorer

• Man kan omdefiniera operatorerna i C++

• Detta gäller dock endast för egna typer

såsom klasser, enums etc.

(16)

class MyInt { public:

const MyInt &operator=(const MyInt &); // tilldeln.

const MyInt &operator+=(const MyInt &); // tilldeln.

const MyInt operator+(int) const; // addition const MyInt operator+(const MyInt &) const;

...

};

MyInt i, j;

i = j + 7; // använd oper+() och oper=() j += i; // använd oper+=()

i.operator+=(j); // operatorer kan användas explicit

Överlagring av operatorer

Exempel på operatoröverlagring

(17)

Överlagring av operatorer

Det är viktigt att tänka på returtyperna för operatorerna

Ta addition som exempel: inget av de ingående objekten innehåller resultatet och därför måste en temporär skapas

Tar man däremot prefix ++-operatorn så håller objektet själv rätt värde och kan returneras som referens

Om returnerade referenser ska vara const är olika från fall till fall och beroende på klassens

användningsområden (ta exempel heltalsklass):

helst const i fallet (a = b) = c

inte nödvändigtvis const om (rect = r).normalize()

Är man osäker härmar man beteendet hos int

(18)

class B;

class A {

int operator()(int, double); // anropsoper B &operator[](int) const; // indexering B &operator[](const char *) const; // (i t.ex. map) const A operator++(int); // postfix inkr.

const A &operator--(); // prefix dekr.

const A operator*(const A &) const; // multiplikation A &operator*(); // avreferering };

const A operator*(int, const A &); // extern mult std::ostream &operator<<(std::ostream &, const A &);

Överlagring av operatorer

Ytterligare exempel på operatoröverlagring

(19)

Polymorfi Polymorfi

Dynamisk bindning Virtuella funktioner Virtuella destruktorer

Strikt virtuella funktioner

Abstrakta basklasser

(20)

Virtuella funktioner

• Normalt sett: kompilatorn vet vilken funktion som skall köras vid funktionsanrop - statisk bindning

• Virtuella funktioner: vilken funktion som körs bestäms av vilket objekt funktionen anropats genom - dynamisk bindning.

Detta kallas polymorfi – beteendet bestäms vid körningstillfället

Polymorfi är endast applicerbart på pekare och referenser eftersom typen på ett objekt är känt vid kompileringstillfället.

(21)

s t r u c t A {

v o i d p r i n t ( ) { s t d : : c o u t < < " A " ; } v i r t u a l v o i d v p r i n t ( ) { s t d : : c o u t < < " A " ; } } ;

s t r u c t B : p u b l i c A {

v o i d p r i n t ( ) { s t d : : c o u t < < " B " ; } v i r t u a l v o i d v p r i n t ( ) { s t d : : c o u t < < " B " ; } } ;

A a ; B b ;

A * a p = & b ; / / o k : B ä r s u b k l a s s t i l l A A & a r = b ; / / o k : a r r e f e r e r a r a

a p - > v p r i n t ( ) ; / / p o l y m o r f i : s k r i v e r u t " B "

a r . v p r i n t ( ) ; / / p o l y m o r f i : s k r i v e r u t " B "

a p - > p r i n t ( ) ; / / e j p o l y m o r f i : s k r i v e r u t " A "

a r . p r i n t ( ) ; / / e j p o l y m o r f i : s k r i v e r u t " A "

b . v p r i n t ( ) ; / / o b j e k t : s k r i v e r u t " B "

B * b p = & a ; / / f e l : A ä r i n t e n e d ä r v d f r å n B

Virtuella funktioner

(22)

Virtuella destruktorer

class Av { public: virtual ~Av(); };

class Bv : public Av { public: ~Bv(); };

class A { public: ~A(); };

class B : public A { public: ~B(); };

B *bp = new B;

A *ap = bp;

delete ap; // fel?: B's destruktor anropas inte

Bv *bvp = new Bv;

Av *avp = bvp;

delete avp; // ok: B's destruktor anropas

För att alla objekt i en arvskedja skall få sina

destruktorer anropade krävs att basklassen har en virtuell destruktor.

(23)

Abstrakta basklasser och strikt virtuella funktioner

En strikt virtuell (pure virtual) funktion tvingar subklasser att ge en definition

• Basklassen kan då inte instantieras och kallas därför abstrakt basklass

• En abstrakt basklass definierar ett

interface som alla nedärvda klasser

måste följa

(24)

cl a ss A {

pu b li c:

v ir t ua l v oi d p ri n t( ) = 0 ; // s t ri kt pg a ' =0 ' };

cl a ss B : pu b li c A {

pu b li c:

v oi d p ri n t( ) ; / / d ef in i ti on må st e g e s om }; / / B s ka l l in s ta nt i er a s

vo i d B: : pr in t () {

s td : :c ou t < < " B" << s t d: :e n dl ; }

.. .

A a ; / / fe l : A ä r en ab st r ak t b as kl a ss

B b ; / / ok : B h a r al l a fu n kt io n er d e fi n ie ra d e b. p ri nt ( ); / / kö r B :: p ri nt ( );

Abstrakta basklasser och

strikt virtuella funktioner

References

Related documents

Det redovisade värdet omfattar inte redovisat värde för en redovisad skuld, om inte återvinningsvärdet inte kan bestämmas utan att hänsyn tas till denna skuld, vilket

• Virtuella funktioner: vilken funktion som körs bestäms av vilket objekt funktionen anropats genom - dynamisk bindning. • Detta kallas polymorfi – beteendet bestäms

• Virtuella funktioner: vilken funktion som körs bestäms av vilket objekt funktionen anropats genom - dynamisk bindning. • Detta kallas polymorfi – beteendet bestäms

De argument som förekommer i Facebook-gruppen Nej tack till moské i Karlstad tar inte någon hänsyn till rådande religionsfrihet. Det är övervägande negativa argument som förekommer

Vissa skillnader i det statistiska resultatet är dock påfallande stora och av den orsaken finns skäl att utifrån dessa resultat resonera kring vad orsakerna till det kan vara..

22 De negativa värdena för variabeln citeringar i modellerna 2-3 indikerar dock ett mycket svagt negativt (men ej signifikant) samband mellan vetenskaplig framgång och

En välgjord observationsmall ska kunna visa på olika samband, exempelvis kunna dra slutsatser om i köpcenter erbjuds främst vissa tjänster medan i vårdnära apotek erbjuds det

Medieorganisationerna gör ett urval av information, händelser och ämnen och presenterar detta för konsumenterna. Prioriteringar görs beroende på hur spektakulär den