Obiektowe programowanie w języku C++
Kurs podstawowy
Dr inż. Lucjan Miękina
upel.agh.edu.pl/wimir/login/
Katedra Robotyki i Mechatroniki
April 9, 2013
1/1
Obiektowe programowanie w języku C++
Reagowanie na sytuacje wyjątkowe
Blok try obejmujący całość kodu funkcji - function try block
Konstrukcji typu function try block używa się, aby umożliwić detekcję wyjątków w
całym zakresie kodu funkcji:
1 void functionTryBlock () try {
2 if (1)
3 throw 2; // generowanie wyjatku typu int
4 }
5 catch ( int & e) {
6 cout << " Exception thrown in functionTryBlock (): " << e << endl ;
7 }
8
9 int main () {
10 functionTryBlock ();
11 return 0;
12 }
Rezultat działania:
1 Exception thrown in functionTryBlock (): 2
2/1
Obiektowe programowanie w języku C++
Reagowanie na sytuacje wyjątkowe
Obsługa wyjątków systemowych
Wyjątki te są generowane automatycznie w trakcie działania programu (przez sprzęt,
programy systemowe lub biblioteki języka C), więc bez udziału programisty, w związku
z tym powstaje jedynie problem ich przechwycenia i odpowiedniego obsłużenia.
Aby przechwycić ten rodzaj wyjątku, w systemach operacyjnych Microsoft Windows
używa się kodu o ogólnej postaci:
1 _try {
2 Body
3 }
4 _except (< wyrazenie_filtrujace >) { // blok obslugi wyjatku
5 Handler
6 }
gdzie Body jest ciałem instrukcji złożonej, w której spodziewane jest wystąpienie
błędu, _except rozpoczyna blok obsługi tego błędu, wyrażenie zaś jest nazywane
filtrującym, jako że jego wartość steruje sposobem obsługi błędu:
EXCEPTION_CONTINUE_EXECUTION ( 1) - wyjątek jest odrzucony i program jest
kontynuowany bez zmian od miejsca wysłania wyjątku
EXCEPTION_CONTINUE_SEARCH (0) - wyjątek jest nieznany na danym poziomie,
należy kontynuować poszukiwanie innego bloku jego obsługi
EXCEPTION_EXECUTE_HANDLER (1) - wyjątek jest rozpoznany i rozpoczyna się
jego obsługa poprzez skok do bloku obsługi zlokalizowanego za słowem _except.
Wyrażenie filtrujące jest obliczane jako wyrażenie języka C. Jeśli jest wymagane
bardziej skomplikowane przetwarzanie, można w tym miejscu wywołać funkcję, która
zwraca jedną z wyżej wymienionych wartości.
3/1
Obiektowe programowanie w języku C++
Reagowanie na sytuacje wyjątkowe
Identyfikatory wyjątków systemowych
Wszystkie wyjątki obsługiwane przez system operacyjny zostały opatrzone
odpowiednimi identyfikatorami. Poniżej podano identyfikatory wybranych wyjątków:
EXCEPTION_ACCESS_VIOLATION - naruszenie dostępu do pamięci
EXCEPTION_ARRAY_BOUNDS_EXCEEDED - niepoprawny indeks do tablicy
EXCEPTION_FLT_DIVIDE_BY_ZERO - dzielenie przez zero
zmiennoprzecinkowe
EXCEPTION_FLT_OVERFLOW - nadmiar zmiennopozycyjny
EXCEPTION_FLT_UNDERFLOW - niedomiar zmiennopozycyjny
EXCEPTION_INT_DIVIDE_BY_ZERO - dzielenie przez zero całkowite
EXCEPTION_INT_OVERFLOW - nadmiar całkowitoliczbowy
EXCEPTION_IN_PAGE_ERROR - błąd strony.
4/1
Obiektowe programowanie w języku C++
Reagowanie na sytuacje wyjątkowe
Funkcje związane z obsługą wyjątków systemowych
GetExceptionCode() zwraca identyfikator wyjątku jako liczbę typu int
GetExceptionInformation() - zwraca wskaznik do struktury zawierającej
dodatkową informację o wyjątku i o stanie procesora w momencie wystąpienia
wyjątku sprzętowego. Struktura ma postać:
1 struct _EXCEPTION_POINTERS {
2 EXCEPTION_RECORD * ExceptionRecord ,
3 CONTEXT * ContextRecord
4 }
Przykład obsługi wyjątku typu naruszenie dostępu do pamięci
1 # include < iostream >
2 # include < windows .h > // dekl . EXCEPTION_ACCESS_VIOLATION
3 # include < excpt .h >
4 int filter ( unsigned int code , struct _EXCEPTION_POINTERS * ep ) {
5 if ( code == EXCEPTION_ACCESS_VIOLATION )
6 return EXCEPTION_EXECUTE_HANDLER ;
7 else
8 return EXCEPTION_CONTINUE_SEARCH ;
9 }
10 int main ( int argc , char * argv []) {
11 int * p = 0;
12 _try {
13 *p = 13; // spowoduje wyjatek typu naruszenie dostepu do pamieci
14 }
15 _except ( filter ( GetExceptionCode () , GetExceptionInformation ())) {
16 cout << endl << " Obsluga wyjatku !";
17 } }
5/1
Obiektowe programowanie w języku C++
Reagowanie na sytuacje wyjątkowe
Unifikacja obsługi wyjątków systemowych i programowych
Dla ujednolicenia metod obsługi tych dwu kategorii wyjątków można zastosować
następujące konstrukcje:
1
zdefiniować własną klasę lub rodzinę klas dedykowaną do obsługi wyjątków
systemowych
2
zdefiniować własną funkcję dedykowaną do obsługi wyjątków systemowych, która
musi być zgodna z poniższą specyfikacją:
1 typedef void (* _se_translator_function )
2 ( unsigned int , struct _EXCEPTION_POINTERS *);
Funkcja ta powinna tworzyć obiekt wyjątku odpowiedniego typu i wysyłać go
instrukcją throw.
3
zainstalować tę funkcję dla każdego wątku programu, używając funkcji
set_se_translator z argumentem wskazującym na własną funkcję dedykowaną
do obsługi wyjątków systemowych. Od tego miejsca w momencie wystąpienia
wyjątku systemowego będzie wywołana ta właśnie funkcja.
6/1
Obiektowe programowanie w języku C++
Reagowanie na sytuacje wyjątkowe
Przykład zunifikowanej obsługi wyjątków systemowych i programowych
1 // kompilowac z opcja : / EHsc
2 # include < stdio .h >
3 # include < windows .h >
4 # include
5
6 class SE_Exception {
7 unsigned int nSE ;
8 public :
9 SE_Exception ( unsigned int n) : nSE (n) {}
10 ~ SE_Exception () {}
11 unsigned int SeNumber () { return nSE ; }
12 };
13 // funkcja uzytkowa
14 void Fun () {
15 char *p = 0;
16 *p = A ;
17 }
18 // wlasna funkcja obslugi wyjatkow systemowych
19 void Handler ( unsigned int u , EXCEPTION_POINTERS * pExp ) {
20 cout << "f. Handler () " << endl ;
21 throw new SE_Exception (u ); // utworzenie i wyslanie wyjatku
22 }
23 int main ( int argc , char * argv []) {
24 try {
25 _set_se_translator ( Handler );
26 Fun ();
27 }
28 catch ( SE_Exception * e) {
29 cout << " Zlapano wyjatek systemowy " << e -> SeNumber ();
30 delete e;
31 } }
7/1
Obiektowe programowanie w języku C++
Reagowanie na sytuacje wyjątkowe
Standardowe klasy wyjątków
Zostały one zdefiniowane w bibliotece standardowej C++ i są gotowe do użycia lub
mogą stanowić podstawę do tworzenia klas pochodnych. Wszystkie te klasy dziedziczą
z klasy exception, zdefiniowanej w pliku nagłówkowym . Dzielą się na 2
kategorie, zdefiniowane w pliku nagłówkowym :
logic_error, która reprezentuje błędy w logice programu, takie jak przekazanie
niepoprawnego argumentu.
runtime_error, która reprezentuje błędy pojawiające się jako rezultat
nieprzewidzianych zdarzeń w trakcie wykonywania programu, takich jak awaria
sprzętu lub brak pamięci.
Zarówno runtime_error jak i logic_error dostarczają konstruktora, który pobiera
argument typu std::string, co umożliwia wprowadzenie opisu wyjątku w
reprezentującym go obiekcie i pozniejsze odczytanie go przy użyciu metody
exception::what, co ilustruje poniższy program.
1 # include < stdexcept >
2 # include < iostream >
3 using namespace std ;
4 class MojWyjatek : public runtime_error {
5 public :
6 MojWyjatek ( const string & opis = "") : runtime_error ( opis ) {}
7 };
8 int main ( int argc , char * argv []) {
9 try {
10 throw MojWyjatek (" Wyjatek 007 " );
11 }
12 catch ( MojWyjatek & x) {
13 cout << x. what () << endl ;
14 } }
8/1
Obiektowe programowanie w języku C++
Reagowanie na sytuacje wyjątkowe
Standardowe klasy wyjątków
Klasy wyjątków dziedziczące z logic_error
domain_error Naruszenie warunku wstępnego
invalid_argument Niepoprawny argument podany przy wywołaniu funkcji
length_error Próba wygenerowania obiektu o rozmiarze większym niż maksymalna wa
out_of_range Argument spoza zakresu
bad_cast Niepoprawne wyrażenie z użyciem dynamic_cast
bad_typeid Wystąpienie wskaznika p o wartości NULL w wyrażeniu typeid(*p)
Klasy wyjątków dziedziczące z runtime_error
range_error Wynik operacji zmiennoprzecinkowej jest za duży lub za mały
overflow_error Wystąpienie nadmiaru przy operacji arytmetycznej
bad_alloc Wystąpienie błędu przy próbie alokacji pamięci
9/1
Obiektowe programowanie w języku C++
Zapis i odczyt danych w trybie binarnym
Zapis i odczyt złożonych danych
Metody służące do zapisu i odczytu danych w trybie binarnym używają wskaznika
typu char", ale nie znaczy to, że ich zastosowanie ogranicza się do tablic znaków.
Można obsługiwać dane dowolnych typów, posługując się rzutowaniem:
1 # include < iostream >
2 # include < fstream >
3 using namespace std ;
4 class Data {
5 int key =0; // non - static data member initializers
6 double value =0.; // only available with - std =c ++11
7 public :
8 Data () { };
9 Data ( int k , double v) : key (k), value (v) { };
10 friend ostream & operator <<( ostream & os , const Data & st );
11 };
12 ostream & operator <<( ostream & os , const Data & d) {
13 os << " key : " << d. key << " , value " << d. value ;
14 return os ;
15 }
16 int main () { 16
17 Data pi (314 , 3.14) , pi2 ; 17
18 cout << endl << pi ; 18 key : 314 , value 3.14
19 ofstream fout (" Data . bin " , ios :: out | ios :: binary ); 19
20 fout . write (( char *)& pi , sizeof ( Data )); 20
21 fout . close (); 21
22 ifstream fin (" Data . bin " , ios :: in | ios :: binary ); 22
23 fin . read (( char *)& pi2 , sizeof ( Data )); 23
24 fin . close (); 24
25 cout << endl << pi2 ; 25 key : 314 , value 3.14
10/1
Obiektowe programowanie w języku C++
Zapis i odczyt danych w trybie binarnym
1 # include < iostream >
2 # include < fstream >
3 using namespace std ;
4
5 class Student {
6 char Name [32];
7 int Grade ;
8 public :
9 friend istream & operator >>( istream & is , Student & st );
10 friend ostream & operator <<( ostream & os , const Student & st );
11 friend ifstream & operator >>( ifstream & is , Student & st );
12 friend ofstream & operator <<( ofstream & is , const Student & st );
13 };
14 istream & operator >>( istream & is , Student & st ) {
15 cout << " Enter student name :" << endl ;
16 is >> st . Name ;
17 cout << " Enter student grade :" << endl ;
18 is >> st . Grade ;
19 return is ;
20 }
21 ostream & operator <<( ostream & os , const Student & st ) {
22 os << endl << " Student " << st . Name << ": Grade " << st . Grade ;
23 return os ;
24 }
25 ifstream & operator >>( ifstream & is , Student & st ) {
26 is . read (( char *) &st , sizeof ( Student ));
27 return is ;
28 }
29 ofstream & operator <<( ofstream & os , const Student & st ) {
30 os . write (( char *) &st , sizeof ( Student ));
31 return os ;
32 }
11/1
Obiektowe programowanie w języku C++
Zapis i odczyt danych w trybie binarnym
33 void save ( Student & s) {
34 ofstream fout (" student . dat " , ios :: binary );
35 if ( fout . is_open ()) {
36 char ans = y ;
37 do {
38 cin >> s;
39 fout << s;
40 cout << endl << " Continue ? " ;
41 cin >> ans ;
42 } while ( ans == y );
43 fout . close ();
44 } }
45 void read ( Student & s) {
46 ifstream fin (" student . dat " , ios :: binary );
47 if ( fin . is_open ()) {
48 while (! fin . eof ()) {
49 fin >> s;
50 if (! fin . eof ())
51 cout << s;
52 }
53 fin . close ();
54 } }
55 int main ( int argc , char * argv []) {
56 char ans ;
57 Student stud ;
58 cout << endl << " Choose - Read , - Write ? " ;
59 cin >> ans ;
60 if ( ans == r || ans == R )
61 read ( stud );
62 if ( ans == w || ans == W )
63 save ( stud );
64 return 0;
65 }
12/1
Obiektowe programowanie w języku C++
Inteligentne wskazniki
auto_ptr, unique_ptr, shared_ptr
13/1
Obiektowe programowanie w języku C++
Dynamiczne struktury danych
Dynamiczne struktury danych są to struktury, które charakteryzują się zmienną ilością
elementów, zmienną konfiguracją wzajemną lub zmiennymi typami. Należą do nich:
wektor (vector)
stos (stack)
kolejka (queue)
lista (list)
zbiór (set)
drzewo (tree)
mapa, słownik (map, dictionary)
graphs and others.
Każda z wymienionych kategorii cechuje się odmienną organizacją wewnętrzną,
sposobem dostępu do elementów i zastosowaniem.
Dynamiczne struktury danych są implementowane przez biblioteki C++, takie jak:
Standard C++ Lib, Boost, Qt, itp.
14/1
Obiektowe programowanie w języku C++
Dynamiczne struktury danych
Standardowa biblioteka C++
Jest to biblioteka klas, które dostarczają implementacji podstawowych algorytmów i
struktur danych potrzebnych w zastosowaniach. Zawiera następujące pakiety klas:
The Language Support Library
The Diagnostics Library
The General Utilities Library
The Standard String Templates
Localization Classes and Templates
The Containers, Iterators and Algorithms Libraries (the Standard Template
Library)
The Standard Numerics Library
The Standard Input/Output Library
C++ Headers for the Standard C Library
Zastosowanie STL do dynamicznych struktur danych
STL jest biblioteką C++ implementującą pojemniki, algorytmy i iteratory; dostarcza
ona wielu podstawowych konstrukcji stosowanych w informatyce.
STL jest to tzw. biblioteka generyczna, co oznacza, że jej składniki są mocno
sparametryzowane za pomocą szablonów i dzięki temu współpracują z typami
wbudowanymi w język, typami wbudowanymi w samą bibliotekę i dowolnymi typami
zdefiniowanymi przez użytkownika.
15/1
Obiektowe programowanie w języku C++
Dynamiczne struktury danych
Główne składniki STL
Klasy pojemników
Ich przeznaczeniem jest przechowywanie obiektów. STL zawiera klasy vector, list,
queue, deque, set, multiset, map, multimap, hash_set, hash_multiset, hash_map, and
hash_multimap.
każda z tych klas jest szablonem, którego instancja może reprezentować dowolny typ.
Na przykład, można użyć klasy vector do przechowywania ciągu danych
całkowitych (jak w tablicy), z tym że vector eliminuje problemy związane z
dynamicznym zarządzaniem pamięcią:
1 vector < int > v (3); // Deklaracja wektora o 3 elementach
2 v [0] = 7;
3 v [1] = v [0] + 3;
4 v [2] = v [0] + v [1]; // v [0] == 7, v [1] == 10 , v [2] == 17
5 // dodanie nowych elementow
6 v. push_back (11);
7 v. push_back (12);
8 v. push_back (13);
9 // usuniecie pierwszego elementu
10 v. pop_front ();
16/1
Obiektowe programowanie w języku C++
Dynamiczne struktury danych
Algorytmy
Algorytmy wykonują operacje na danych przechowywanych w pojemnikach. Na
przykład, aby odwrócić uporządkowanie elementów w obiekcie klasy vector, można
użyć algorytmu reverse.
1 reverse (v. begin () , v. end ()); // v [0] == 17 , v [1] == 10 , v [2] == 7
Można zauważyć, że reverse jest funkcją globalną, a nie składową. Ponadto, wymaga
ona dwu argumentów, ponieważ wykonuje działanie na elementach z zadanego
zakresu, a nie na pojemniku. W tym szczególnym przypadku zakres jest całym
pojemnikiem v.
Uzasadnienie dla tych rozwiązań: funkcja reverse, podobnie jak inne algorytmy STL,
jest niezależna od klas pojemników. Oznacza to, że reverse można użyć nie tylko do
zmiany porządku elementów wektora, ale również listy, a nawet elementów tablic, na
przykład:
Rezultat działania:
1 const int N =5;
2 double A[N] = { 1.1 , 1.2 , 1.3 , 1.4 , 1.5 }; 1 A [0] = 1.5
3 reverse (A , A + N ); 2 A [1] = 1.4
4 int i; 3 A [2] = 1.3
5 for (i = 0; i < N; ++ i) 4 A [3] = 1.2
6 cout << "A[" << i << "] = " << A[i ]; 5 A [4] = 1.1
Podobnie jak przy odwracaniu porządku elementów wektora, użyto tu zakresu.
Pierwszy argument reverse jest wskaznikiem do początku zakresu, a drugi argument
wskazuje jeden element za końcem zakresu. Zakres wynosi [A, A + N); w notacji
asymetrycznej.
Inne algorytmy implementowane przez STL to: insert, copy, remove, sort, find, etc.
17/1
Obiektowe programowanie w języku C++
Dynamiczne struktury danych
Iteratory
Iteratory zapewniają dostęp do elementów pojemnika bez wnikania w jego wewnętrzną
organizację. Iteratory są uogólnieniem wskazników. Wskazniki są iteratorami, dlatego
można użyć algorytmu reverse do elementów tablicy. Podobnie, vector deklaruje
wbudowane typy iterator i const_iterator. W powyższym przykładzie, typ zwracany
przez v.begin() i v.end() jest vector:: iterator . Iteratory pozwalają uniezależnić
algorytmy od pojemników: algorytmy są szablonami, parametryzowanymi typem
iteratora, więc nie są ograniczone do typu pojemnika. Na przykład, liniowe
przeszukiwanie zakresu, implementowane w STL przez algorytm find:
1 template < class Iterator , class T >
2 Iterator find ( Iterator first , Iterator last , const T& value ) {
3 while ( first != last && * first != value ) ++ first ;
4 return first ;
5 }
find ma trzy argumenty: dwa iteratory definiujące zakres, i wartość poszukiwaną w
zakresie. find sprawdza każdy iterator w zakresie [first, last), idąc od początku do
końca, zatrzymuje się gdy znajdzie iterator wskazujący value lub gdy dojdzie do końca
zakresu. first i last są zadeklarowane jako typ Iterator, który jest parametrem
szablonu. Tzn, że nie ma konkretnego typu Iterator: przy każdym wywołaniu find,
kompilator zastępuje parametry Iterator i T aktualnymi typami argumentów. Na
przykład, jeśli dwa pierwsze argumenty find są typu int" i trzeci jest typu int, to w
istocie wywołana będzie funkcja:
1 int * find ( int * first , int * last , const int & value ) {
2 while ( first != last && * first != value ) ++ first ;
3 return first ;
4 }
18/1
Obiektowe programowanie w języku C++
Dynamiczne struktury danych
Dostępne są zwykle iteratory:
iterator swobodny dostęp do elementu dla zapewnienia odczytu lub modyfikacji
jego wartości
const_iterator swobodny dostęp do elementu dla zapewnienia odczytu jego
wartości. Próba modyfikacji elementu udostępnionego tym iteratorem skutkuje
błędem.
reverse_iterator jak iterator, ale dostęp jest realizowany w kolejności odwrotnej
const_reverse_iterator jak const_iterator, ale dostęp jest realizowany w
kolejności odwrotnej
19/1
Obiektowe programowanie w języku C++
Dynamiczne struktury danych
Zastosowanie klasy vector do elementów o typach standardowych
Pojemnik typu vector przechowuje dane w liniowym obszarze pamięci, co zapewnia
swobodny dostęp do nich można ten pojemnik indeksować liczbą całkowitą,
podobnie jak zwykłe tablice. Niestety, wstawienie nowego elementu gdziekolwiek
indziej, niż na końcu jest operacją liniowego czasu, gdyż trzeba "odsunąć" elementy,
żeby zrobić miejsce na nowy. Ilość elementów może się zmieniać, dzięki
automatycznemu zarządzaniu pamięcią.
1 # include < iostream >
2 # include < vector >
3 # include < algorithm >
4 using namespace std ;
5 void print ( vector < int >& v) {
6 vector < int >:: const_iterator it ;
7 cout << "v: [ ";
8 for ( it =v. begin (); it != v. end (); it ++)
9 cout << * it << " ";
10 cout << "]" << endl ;
11 }
12 int main ( int argc , char * argv []) {
13 // Initially v contains 0 elements .
14 vector < int > vec ;
15 // Insert an element 1 at the end
16 vec . push_back (1);
17 // Insert 2 other elements at the end
18 vec . push_back (2);
19 vec . push_back (0); print ( vec ); 19 v: [ 1 2 0 ]
20 sort ( vec . begin () , vec . end ()); print ( vec ); 20 v: [ 0 1 2 ]
21 // remove the last element 21
22 vec . pop_back (); print ( vec ); 22 v: [ 0 1 ]
23 } 23 .
20/1
Obiektowe programowanie w języku C++
Dynamiczne struktury danych
vector wskazników do obiektów
1 # include < iostream > 30 int main ( int argc , char * argv []) {
2 # include < vector > 31 vector < Complex *> v;
3 # include " ../ Complex / Complex .h" 32 Complex * c;
4 using namespace std ; 33 v. push_back ( new Complex ("1" ,1. ,1.));
5 void print ( vector < Complex * >& v) { 34 c = new Complex ("2" ,2. ,2.);
6 // declaration of a suitable iterator 35 v. push_back (c );
7 vector < Complex * >:: const_iterator it ; 36 v. push_back ( new Complex ("3" ,3. ,3.));
8 cout << endl << " vector contains " 37 print (v );
9 << v. size () << " elements :"; 38 erase (v , 1); // remove the 2 nd element
10 for ( it =v. begin (); it != v. end (); it ++) 39 print (v );
11 cout << endl << ** it ; 40 erase (v ); // remove all elements
12 } 41 print (v );
13 void erase ( vector < Complex * >& v , int i) 42 return 0;
14 { 43 }
15 vector < Complex * >:: iterator it ;
16 it =v. begin ()+ i; 1 1: 0 xd96010 , (1.0 , 1.0) created
17 if ( it != v. end ()) { 2 2: 0 xd96060 , (2.0 , 2.0) created
18 delete * it ; 3 3: 0 xd960b0 , (3.0 , 3.0) created
19 v. erase ( it ); 4 vector contains 3 elements :
20 } 5 Re =1 , Im =1
21 } 6 Re =2 , Im =2
22 void erase ( vector < Complex * >& v) { 7 Re =3 , Im =3
23 while (v. size ()) { 8 2: 0 xd96060 , (2.0 , 2.0) deleted
24 Complex * c = v. back (); 9 vector contains 2 elements :
25 if (c) 10 Re =1 , Im =1
26 delete c; 11 Re =3 , Im =3
27 v. pop_back (); 12 3: 0 xd960b0 , (3.0 , 3.0) deleted
28 } 13 1: 0 xd96010 , (1.0 , 1.0) deleted
29 } 14 vector contains 0 elements :
21/1
Obiektowe programowanie w języku C++
Dynamiczne struktury danych
vector obiektów
1 # include < iostream > 30 erase (v , 1); // remove the 2 nd element
2 # include < vector > 31 print (v );
3 # include " ../ Complex / Complex .h" 32 v. clear (); // remove all elements
4 using namespace std ; 33 print (v );
5 void print ( vector < Complex >& v) { 34 return 0;
6 // declaration of a suitable iterator 35 }
7 vector < Complex >:: const_iterator it ;
8 cout << endl << " vector contains " 1 1: 0 x7fffa13c2d60 , (1.0 , 1.0) created
9 << v. size () << " elements :"; 2 1: 0 x1e8f010 , (1.0 , 1.0) created
10 for ( it =v. begin (); it != v. end (); it ++) 3 2: 0 x1e8f060 , (2.0 , 2.0) created
11 cout << endl << * it ; 4 1: 0 x1e8f040 , (1.0 , 1.0) created
12 } 5 1: 0 x1e8f010 , (1.0 , 1.0) deleted
13 void erase ( vector < Complex >& v , int i) 6 3: 0 x1e8f0d0 , (3.0 , 3.0) created
14 { 7 1: 0 x1e8f090 , (1.0 , 1.0) created
15 vector < Complex >:: iterator it ; 8 2: 0 x1e8f0b0 , (2.0 , 2.0) created
16 it =v. begin ()+ i; 9 1: 0 x1e8f040 , (1.0 , 1.0) deleted
17 if ( it != v. end ()) { 10 2: 0 x1e8f060 , (2.0 , 2.0) deleted
18 v. erase ( it ); 11 vector contains 3 elements :
19 } 12 Re =1 , Im =1
20 } 13 Re =2 , Im =2
21 int main ( int argc , char * argv []) { 14 Re =3 , Im =3
22 vector < Complex > v; 15 3: 0 x1e8f0d0 , (3.0 , 3.0) deleted
23 Complex c("1" ,1. ,1.); 16 vector contains 2 elements :
24 v. push_back (c ); 17 Re =1 , Im =1
25 c. Set ("2" , 2. , 2.); 18 Re =3 , Im =3
26 v. push_back (c ); 19 1: 0 x1e8f090 , (1.0 , 1.0) deleted
27 c. Set ("3" , 3. , 3.); 20 2: 0 x1e8f0b0 , (3.0 , 3.0) deleted
28 v. push_back (c ); 21 vector contains 0 elements :
29 print (v ); 22 3: 0 x7fffa13c2d60 , (3.0 , 3.0) deleted
22/1
Wyszukiwarka
Podobne podstrony:
Wyklad CPP 6
Wyklad CPP 1
Wyklad CPP 2
Wyklad CPP 7
Wyklad CPP 3
CPP WYKLAD 1
CPP WYKLAD 7
CPP WYKLAD 6
CPP WYKLADY ANALIZA 2
CPP WYKLAD 1 2
CPP WYKLAD 3
CPP WYKLAD 4 5
CPP WYKLADY ANALIZA 1
Sieci komputerowe wyklady dr Furtak
Wykład 05 Opadanie i fluidyzacja
więcej podobnych podstron