Klasa podstawy



Pobieranie 0,54 Mb.
Strona1/5
Data23.04.2018
Rozmiar0,54 Mb.
  1   2   3   4   5

Środa 1.02 zero


Poni 13.02 pierwszy

Ponied 20.02 drugi


Współbieżne
Wtorek 24.01.02 -9.30

Wtorek 31.02.02 – 9.30




Wskaźniki




Deklaracja zmiennych wskaźnikowych (wskaźników)
int * wsk_i; float * wsk_f; char * wsk_c; void * wsk_v;

int unsigned * wsk_iu;



Operacje na zmiennych wskaźnikowych


Operacje na wartościach zmiennych wskaźnikowych

Wskaźnik służący do pokazywania na obiekty jednego typu nie nadaje się do pokazywania na obiekty innych typów1.
wsk_iu = wsk_i; // poprawne

wsk_f = wsk_i // błąd!!!

wsk_f = (float *) wsk_i; // poprawne (rzutowanie)

wsk_v = wsk_i; // poprawne

wsk_v = wsk_f; // poprawne
wsk_f = wsk_v; // błąd!!!

Wskaźnik każdego (niestałego) typu można przypisać wskaźnikowi typu void.

void < ------------ dowolny wskaźnik (nie const)

Odwrotne przypisanie nie możliwe;

dowolny wskaźnik < ------------ void // błąd

rzutowanie :

wsk_i = (int *) wsk_v; wsk_f = (float *) wsk_v; wsk_c = (char*) wsk_v;

//wszystkie powyższe instrukcje poprzez zastosowanie rzutowania //są poprawne

Odczytywanie wartości zmiennych, na które pokazują zmienne wskaźnikowe, tzn. których adresy są przechowywane przez zmienne wskaźnikowe.

int a=32; float b=4.4;


int *wsk_i=&a; float *wsk_f=&b ; // & - operator wyłuskiwania adresu

//zmiennej

// wartością zmiennej wsk_i jest adres zmiennej a

// wartością zmiennej wsk_f jest adres zmiennej b


cout<<*wsk_f<// tzn. wypisze wartość zmiennej, której adres jest

// wartością zmiennej wskaźnikowej wsk_f

// * operator wyłuskania wartości zmiennej, na którą

// pokazuje wskaźnik wsk_f

cout<<*wsk_i<

cout<

cout<
*wsk_i = 344; // zmiana wartości zmiennej a = 344

*wsk_f = 4.5;

*wsk_i =*wsk_f // zmiana wartości zmiennej a = 4 (trywialna konwersja

// float- int


Przypomnienie: nie istnieje niejawna trywialna konwersja (np. float* - int*)

przy przepisywaniu wartości wskaźników (zmiennych wskaźnikowych). Wskaźnik służący do pokazywania na obiekty jednego typu nie nadaje się do pokazywania na obiekty innych typów.


wskaźnik typu void

void *wsk_v;

wsk_v=wsk_i;

//cout <<*wsk_v; // niepoprawne

cout <<*(float*)wsk_v; // wartość nieokreślona

cout <<*(int*)wsk_v; // wypisze 34 czyli wartość zmiennej a

//wsk_i=wsk_v; // błąd

wsk_i=(int*)wsk_v; // poprawne


#include

#include
int a=32; float b=4.4;
////////////////////

float *wsk_f=&b ;

int *wsk_i=&a;

////////////////////

void main()

{

clrscr();



wsk_f=&b;

wsk_i=&a;

cout<<*wsk_f<

cout<<*wsk_i<

cout<

cout<

*wsk_i=*wsk_f; //poprawne-przepisywanie wartości(konwersja

//trywialna)

// wsk_i=wsk_f; //niepoprawne

// wsk_f=wsk_i; //niepoprawne

wsk_i = (int*)wsk_f; // poprawne (rzutowanie)

//wsk_i =(int*)&b; // równoważne instrukcji wsk_i = (int*)wsk_f;

cout<

//zmiennej wsk_f

cout<<(float*)*wsk_i<

cout<<*(float*)wsk_i<

cout<<(float)*wsk_i<

cout<<*wsk_i<
// to samo w odwrotną stronę z float * --> int *

a=34;


wsk_i=&a;

wsk_f =(float*)wsk_i;

cout<<*(int*)wsk_f<

}

Wskaźniki stałe i do stałych

int const stala = 22;

int const *wsk_ic=&stala;

wsk_v = wsk_ic; // błąd nie można wskaźnikowi typu void * przypisać

// wskaźnika do obiektu typu const

int const *wsk_ic=&stala;

int const *wsk_v = wsk_ic; // ok.

wsk_v = &stala ; // ok.
int * const wsk_ci=&wsk_i;

wsk_v = wsk_ci; //ok


Zastosowania wskaźników:

  • ulepszenie pracy z tablicami,

  • przesyłanie do funkcji argumentów przez adres (również argumentów będących wskaźnikami do funkcji) co pozwala na zmianę wartości przesyłanych argumentów, lub w przypadku funkcji możliwość wywoływania różnych funkcji w ciele innej funkcji,

  • dostęp do specjalnych komórek pamięci

  • rezerwację obszarów pamięci (zmienne dynamiczne)


Zastosowanie wskaźników w pracy z tablicami

int * wsk_i; int tab [4];

wsk_i = &tab[0] ; == wsk=tab;

przesuwanie wskaźnika: wsk_i++; wsk=wsk+n;


*wsk++ ; (*wsk)++;

for (int i =0; i<4; i++)

*(wsk++) = i+10; // tab = [10,11,....,13]

Nazwa tablicy, a wskaźnik

wsk_i=tab;


tab[3] równoważne *(tab+3)
wsk_i[3]; *(wsk_i+3)
wsk_i++; //ok. tab++; // błąd

Nazwa tablicy jest jakby stałym wskaźnikiem do jej zerowego elementu.



Dlaczego jakby? Ponieważ nazwa tablicy nie jest obiektem. Stąd:

int * wsk_i; // wskaźnik to jakaś zmienna, obiekt

&wsk // to jest jego adres

&tab // błąd – nazwa nie jest obiektem. Tablica tak, nazwa nie.


wskaźnik do wskaźnika

int ** wsk_wi; int * wsk_i; int a;

wsk_wi = &wsk_i;
Arytmetyka wskaźników TABLICE

Wskaźnik do składników klasy

int a;

int * wsk = &z1.re;

class l_zes {

public:


int re;

int im;


public:

//...........konstruktory

};

wsk


l_zes z1;

int * wsk_z = &z1.re //można bo publiczny składnik

int l_zes::*wsk_do_kl;
Zwykły wskaźnik pokazuje na konkretne miejsce w pamięci, określony adres.

Wskaźnik do składnika klasy nie pokazuje na żadne konkretne miejsce w pamięci, ale określa przesunięcie w pamięci od początku obiektu do składnika klasy.
int l_zes::*wsk_do_kl = &l_zes::re;

l_zes z1, z2; z2.*wsk_do_kl;

z1.*wsk_do_kl;
l_zes * wsk=&z1;

wsk->*wsk_do_kl;



Uwaga: nie można pokazywać na składniki nie publiczne.

nie można pokazac na coś co nie posiada nazwy. Na tablice można na jej np. piąty element nie, bo nie posiada nazwy.


class string {

public:


char *wsk;

int roz;


public:

//...konstruktory

};
char *string:: *wsk_do_sk; string s1(“jakis lancuch”);

wsk_do_sk = &string::wsk;

*(s1.*wsk_do_sk) =’s’;

cout << *(( s1.*wsk_do_sk)+2);


Wskaźnik do funkcji składowych
class l_zes {

int re;


int im;

public:


//...konstruktory

void wypisz();

int ini(int a, int b);

};


int (l_zes::*wsk_fun_sk) (int, int); void (l_zes::*wsk_fun_sk1) ()
wsk_fun_sk = &l_zes:: ini;

l_zes z1; (z1.*wsk_fun_sk) (2,11);



Składnik statyczny klasy

Na składnik statyczny klasy należy pokazywać zwykłym wskaźnikiem, ponieważ ten składnik nie jest elementem konkretnego obiektu.


class klasa {

static char st;

int cos;

public:


klasa (int ini):cos(ini){}

static char daj() {st=999;

return st;}

int funkcja() {cout << cos; return cos;}

};

////////////////////



char klasa::st;

klasa k1(12), k2(33);

int (klasa::*fun_zwy)()=&klasa::funkcja;

int (klasa::*fun_zwy1)()=klasa::funkcja;

//char (klasa::*fun_sta2)()=&klasa::daj; // blad

//char (klasa::*fun_sta2)()= klasa::daj; // blad

char (*fun_sta)()=&klasa::daj; // ok

char (*fun_sta1)()=klasa::daj; // ok

//////////////

void main()

{

clrscr();



fun_zwy=&klasa::funkcja; //obydwa prawidlowe dlaczego

(k1.*fun_zwy)();

fun_zwy1=klasa::funkcja; //

(k2.*fun_zwy1)();

getchar();

}
Przykład 2

class klasa {

static int st;

//int cos;

public:


int cos;

klasa (int ini):cos(ini){}

static void daj() {st=999; return st;}
//////////

static int st1;

//..............

};

int klasa::st1;



int klasa::st;

klasa k1(12), k2(33);

klasa *wsk1 = &k1;

void main()

{

klasa::st1=90;



clrscr();

cout<<&((klasa*)0)->cos;

cout<cos<

((klasa*)0)->daj();

((klasa*)&k1)->daj();

cout<<((float *)0)<<'\n';

int g;

cout<<((klasa*)g)->cos;



((klasa)g).cos=77;

cout<

cout<<((klasa*)g)->cos; // okreslone nie wypisuje 77

cout<<((klasa*)wsk1)->cos; // okreslone bo wsk1->k1

((klasa*)&k1)->daj(); // okreslone bo k1

cout<<((float *)0)<<'\n';

getchar();

}



  1   2   3   4   5


©operacji.org 2017
wyślij wiadomość

    Strona główna