Date post: | 03-Jan-2016 |
Category: |
Documents |
Upload: | samantha-golden |
View: | 26 times |
Download: | 2 times |
ÚVOD DO C++ 4
Pole, ukazatele a odkazy
4. Pole objektů4.1.Ukazatelé na objekty, použití4.2. Ukazatel this4.3. Dynamická alokace paměti - new - delete4.4. Inicializace dynamicky alokovaného objektu4.5. Dynamická alokace jednorozměrného pole4.6. Odkazy v C++
Pole objektůObjekty jsou proměnné obdobných vlastností jako v jazyku C.Pole objektů je určeno - velikostí pole - bázovým typem pole ( typem je třída )
Syntaxe:
Deklarace pole objektů : Class Trida { int a;public:void nastav_a ( int n) { …….void predej_a ( ) { ………..} ;
Int main(){ Trida pole_objektu[ 5 ]; // deklarave pole objektů o 5_ti prvcích …….}
Do pole objektů je zapisována řídící proměnná cyklu pomocí fce nastav_a()a opět vypsána : */#include<iostream>using namespace std;class Vzorek { // použit implicitní konstruktor a destruktor int a;public: void nastav_a( int n) { a=n;} int vypis_a() { return a;}};int main(){ int i; Vzorek pole_objektu[4]; //Deklarace pole objektů// Zápis do pole objektů: for( i=0;i<4; i++) pole_objektu [ i ].nastav_a( i ); /* Členská funkce nastav_a( i ); je volána pro každý prvek pole *///Výpis pole objektů: for( i=0; i<4; i++){ cout << pole_objektu[i].vypis_a( ) << "\n"; }system(“pause”);return 0;}
Inicializace pole objektů.Podmínkou pro provedení inicializace je explicitní konstruktor deklarovaný v typové třídě. Příklad inicializace pole objektů: class Vzorek { int a; public:// explicitní konstruktor: Vzorek ( int n) { a= n; }//členská funkce: int predej_a() { return a; }};int main(){ //Deklarace jednorozměrného pole s inicializací: Vzorek pole_objektu[4] = { -1, -2, -3, -4 } ; int i; cout<<"Vypis pole objektu :\n"; for( i=0; i<4; i++ ){ cout << pole_objektu[i].predej_a() << ' '; } cout << "\n"; systém(“pause“); return 0;}
Vícerozměrná pole objektu.Deklarace je stejná jako v C.Příklad dvojrozměrného pole a jeho inicializace :class Vzorek { int a;public://konstruktor - podmínka pro provedení inicializace : Vzorek ( int n ) { a=n;}//členská funkce: int predej_a() { return a ;}};int main(){//Deklarace dvojrozměrného pole s inicializací : Vzorek pole_objektu [4][2] = { 1, 2, 3, 4, 5, 6, 7, 8, }; int i; cout << "Vypis pole_objektu[4][2]:\n\n"; for( i=0; i<4; i++) { cout << pole_objektu[i][0].predej_a() << ' '; cout << pole_objektu[i][1].predej_a() << "\n"; }systém (“pause“);return 0;}
Inicializace pole v případě použití konstruktoru s více parametry.
Přebírá-li konstruktor více než jeden argument, jenutné k inicializaci pole použít při inicializaci standardní dlouhou formu.
Tento formát inicializace lze použít i když objekt přebírá pouze jediný argument.Zkrácená forma je však v tomto případu pohodlnější.
#include<iostream>using namespace std;
class Vzorek { int a, b;public://konstruktor : Vzorek ( int n, int m ) { a=n; b=m;}//členské funkce : int predej_a() { return a;} int predej_b() { return b;}};
int main(){/* Inicializace je provedena přímým voláním konstruktoru Vzorek(n,m) */
Vzorek pole_objektu[4][2] = { Vzorek(1, 2),Vzorek(3, 4), Vzorek(5, 6),Vzorek(7, 8), Vzorek(9,10),Vzorek(11,12), Vzorek(13,14),Vzorek(15,16) }; int i; cout << "Vypis pole_objektu[4][2]:\n\n"; for( i=0; i<4; i++){ cout << pole_objektu[i][0].predej_a() << ' '; cout << pole_objektu[i][0].predej_b() << "\n";
cout << pole_objektu[i][1].predej_a() << ' '; cout << pole_objektu[i][1].predej_b() << "\n"; } systém(“pause“); return 0;}
4.1. Ukazatelé objektu - použitíObjekty mohou být dosažitelné pomocí ukazatele na objekt.Adresu objektu získáme použítím adresního operátoru & Použití ukazatele na objekt vyžaduje nahradit operátor tečka operátorem šipkaV C++ platí stejně i aritmetika ukazatelů jako v C. ( inkrementace ukazatele způsobí přechod na nasledující prvek pole objektů ).
Příklad :#include <iostream >using namespace std;class Vzorek { int a, b;public:/*konstruktor má dva parametry (n,m), proto bude inicializace provedena dlouhou formou */Vzorek( int n, int m) { a = n; b=m; }// členské funkce:int predej_a() { return a;}int predej_b() { return b;}};
int main(){//Při inicializaci je nutné použít dlouhou formu: Vzorek pole_objektu[4] = { Vzorek(1,2), Vzorek(3,4), Vzorek(5,6), Vzorek(7,8) }; int i; Vzorek *p_pole_objektu; p_pole_objektu = pole_objektu; /* název pole objektů obsahuje adresu prvního prvku pole objektů Výpis obsahu pole_objektu[ ] pomoci aritmetiky ukazatelů: */cout<<"Vypis pole objektu pomoci aritmetiky "; cout << " ukazatelu\n";for( i=0; i< 4; i++){ cout << p_pole_objektu -> predej_a() << ' '; cout << p_pole_objektu -> predej_b() << "\n";/* inkrementace ukazatele - postup k dalšímu objektu */ p_pole_objektu ++; } system("Pause"); return 0;}
4.2. Ukazatel this ( pseudoproměnná ).
Metoda musí být informována, s jakou instancí má pracovat. Proto je nestatickým metodám předáván implicitní, skrytý parametr ukazatel na aktuální instanci.Předává se automaticky včetně konstruktorů a destruktorů.
Název pseudoproměnná získal this proto, že na rozdíl od proměnných, které definuje programátor, definuje pseudoproměnnou this překladač. Častěji má však název ukazatel this.
Ukazatel this - je typu ukazatel na třídu, které je objekt instancí - ukazuje na aktuální objekt, kterému je zasílána zpráva
V každém objektu je k dispozici ukazatel this na tento objekt a tento fakt si lze představit tak, že v každé třídě (př. class T_třída) je implicitně deklarován atribut
T_třída *const this
jehož hodnotu nemůžeme měnit !!!
Příklad.: Objekt2 . f1_členská( );
f1_členská( ) předává automaticky ukazatel this na Objekt2, který aktivoval volání,protože f1() - je funkce členská, - není spřátelená - není označená static..Příklad požití při odkazování na atribut n třídy T.Parametr metody nastav( int n) zakryje viditelnost atributu stejného jména: class T_trida { int n; public: void nastav( int n); ..... } //end class
void T_trida:: nastav( int n ) { this ->n = n; }
#include<iostream> // demonstrace this#include<cstring>using namespace std;
class Inventarni_zaznam { char polozka[80]; double cena_polozky; int skladovano_pocet;public:// konstruktor : Inventarni_zaznam( char *p_zdroj, double cena, int skl) { strcpy (this ->polozka, p_zdroj); // strcpy(polozka,p_zdroj); this ->cena_polozky =cena; // cena_polozky=cena; this ->skladovano_pocet = skl; //skladovano_pocet = skl; }//členská funkce: void zobraz();}; // end třídy
//Definice členské funkce: pokračovánívoid Inventarni_zaznam::zobraz(){ cout << "Nazev polozky: " << this ->polozka <<"\n";//cout << "Nazev polozky: " << polozka <<"\n";
cout << "Cena :" << this ->cena_polozky << "Kc"<<"\n";//cout << "Cena :" << cena_polozky << "Kc"<<"\n";
cout << "Pocet kusu na sklade: "; cout << this ->skladovano_pocet<<"\n";//cout << skladovano_pocet<<"\n";}
int main(){ Inventarni_zaznam objekt("Budvar",25.70,54); objekt.zobraz(); system("Pause"); return 0;
4.3. Dynamická alokace - new a deleteFunkce malloc( ) a free( ), známé z jazyka C pro alokaci a uvolnění paměti lze použít i v C++.
Navíc lze požít v C++ nový způsob přidělování a uvolňování paměti pomocí funkcí new - protějšek malloc( ) delete - protějšek free( )Uvedené funkce lze použít bez omezení, ( jsou to standardní funkce),
ale použití new a delete v jazyce C++ je - bezpečnější - pohodlnější.
Výhody používání new a delete: - new automaticky přiděluje dostatek paměti pro uložení objektu daného typu a proto není nutné používat fci sizeof(). - automaticky vrací ukazatel určeného typu, není nutné provádět přetypování - obě fce, delete i new mohou být přetěžovány - není nutné vkládat < cstdlib > - umožňují inicializovat dynamicky alokovaný objekt
Dynamické proměnné v C++.Dynamické proměnné - paměť je jim přidělena až za běhu programu.Příkazem za běhu programu je jim přidělená paměť i uvolněna.Přidělení paměti - syntaxe : new typ_proměnné;Typ_proměnné - označení typu proměnné, pro kterou provádíme alokaci.Průběh:Operátor new vyčlení ve volné paměti místo potřebnépro alokaci daného typu a vrátí ukazatel na alokovanou paměť.Příklad alokace: int *p_i = new int ; Není-li dostatek paměti k provedení alokačního příkazu,vrátí new prázdný ukazatel nebo vygeneruje výjimku.Není-li vyjímka programem obsloužena, program bude ukončen. (závisí to na překladači ).Před použitím paměti je nutné otestovat hodnotu ukazatele, vráceného operátorem new, zda není prázdný ( selhání alokace ). Dynamicky přidělenou paměť pro proměnnou lze uvolnit použitím operátoru delete s argumentem ukazatel na přidělenou paměť.Syntaxe: delete p ;
#include<iostream>using namespace std;int main( ){ int *p_int;
p_int = new int; // alokace paměti pro integer
//TEST PŘED POUŽITÍM ALOKOVANÉ PAMĚTI : if( !p_int ) { cout << "Chyba pri alokaci pameti\n"; return 1; }//Zapis do alokovane pameti: *p_int = 100; cout << "Vypis hodnoty v alokovane pameti "; cout << "*p_int :"<< *p_int <<"\n";//Uvolneni pameti: delete p_int; system("Pause"); return 0;}
Inicializace dynamicky alokovaných proměnných a objektů pomocí operátoru new.Syntaxe inicializace proměnné :
ukazatel = new jméno_typu( parametr_inicializace )
Operátor new1) vyčlení z volné paměti prostor pro vytvoření instance odpovídající typu proměnné2) uloží do něj honotou uvedenou jako parametr_inicializace3) vrátí adresu alokované paměti - viz ukazatel.Příklad:/* Program přidělí dynamicky paměť pro proměnnou typu integer a zároveň provede její inicializaci na hodnotu 9.*/ #include<iostream>using namespace std;int main(){ int *p_int;p_int new int(9();……………….…………….
Příklad inicializace proměnné, new má pouze jeden parametr:
int main(){ int *p_int;//Alokace paměti pro proměnnou integer - inicializace hodnotou 9: cout<<"Alokace pameti pro integer byla provedena "; cout<<"prikazem p_int = new int( 9 );\n"; p_int = new int ( 9 );
if(!p_int ) { cout << "Chyba alokace pameti\n"; return 1; } cout << "Vypis hodnoty dereferenci *p_int :"; cout << *p_int << "\n";
// Uvolnění paměti delete p_int; systém(“pause”); return 0;}
Dynamická alokace objektu, inicializace s předáním více parametrů.
Syntaxe inicializace objektu :
ukazatel = new jméno_objetového_typu( parametry_inicializace )
parametry_inicializace – jsou parametry konstruktoru
Příklad inicializace dynamicky vytvořeného objektu, dva inicializační parametry:#include<iostream>using namespace std;class Vzorek { int i,j;public://konstruktor s parametry - inicializace: Vzorek( int a, int b) { i=a; j= b;}//clenska funkce: int predej_soucin() { return i*j; } int vypis_i () { return i;}; int vypis_j () { return j;};}; pokračování
pokračováníint main(){ Vzorek *p_objekt;
/*Alokace objektu s inicializaci: automaticky je volán konstruktor a ten provede inicializaci hodnotou 6 a 5 */
p_objekt = new Vzorek( 6, 5 );
//Test úspěšnosti alokace: if(!p_objekt) { cout << "Chyba alokace pameti\n"; return 1; }
cout << "Soucin je : " << p_objekt -> predej_soucin();//Uvolněni paměti: delete p_objekt; systém(“pause”); return 0;}
Dynamicka alokace pole (s použitím operátoru new ).
Pole, které je dynamicky alokováno, nelze při vytvoření inicializovat !!!!
Syntaxe:Pro vytvoření jednorozměrného pole bude mít operátor new formát :
ukazatel = new typ_pole [ velikost_pole ] ;
Pro uvolnění tohoto dynamicky alokovaného pole bude mít operátor delete formát :
a) pro starší překladače: delete [ velikost_pole ] ukazatel;
b) pro moderního překladače : delete [ ] ukazatel;
Překladač zavolá destruktor pro každý prvek pole.
Příklad - vytvoření dynamického pole objektů:/* Vytvoření dynamického pole 8-mi objektů, atributy objektů zapsány pomocíčlenské fonkce nastav_ij( ) : */class Vzorek { int i,j;public:void nastav_ij( int a, int b){ i =a; j =b; } int predej_soucin( ) { return i*j;}} ; int main(){ Vzorek *p_pole; int i;p_pole = new Vzorek[ 8 ]; // zde provédt test úspěšnosti alokace//Zapis do pole objektů, hodnota j = i : for( i=0; i< 8; i++ ) { p_pole[i].nastav_ij (I , I ); }
delete[] p_pole; getchar(); return 0;}
Příklad - předchozí verze programu doplněnáo destruktor.Ten je volán pro každý prvek pole, kterým je objekt, tedy volán 10-krát./* Vytvoření dynamického pole 10-ti objektů :když je uvolňováno pole, je postupně volán destruktor každého objektu t.j.10-krat */#include<iostream>using namespace std;class Vzorek { int i,j;public://destruktor: ~ vzorek() { cout <<" Destrukce..... \n"; }//členské funkce: void nastav_ij( int a, int b){ i=a; j=b; } int predej_soucin() { return i*j;}};int main(){ Vzorek *p_pole; int i;//Alokace pole:p_pole = new vzorek[10]; pokračování
//Zapis do pole, j = i : …….//Vypis pole:………………….delete[ ] p_pole;//volá pro každý prvek pole, kterým je objekt, destruktorreturn 0;}Výpis programu:Soucin [ 0 ] = 0Soucin [ 1 ] = 1Soucin [ 2 ] = 4.Soucin [ 9 ] = 81 destruktor je volán 10 krát :Destrukce.....Destrukce.....Destrukce.....Destrukce.....Destrukce.....Destrukce.....Destrukce.....Destrukce.....Destrukce.....Destrukce.....
Odkazy