Ć
wiczenia 12 VI 2012
Zadanie 10.3:
Napisać program, który odwołując się do funkcji potega (zdefiniowanej przed programem) dla liczb
całkowitych z określonego przedziału, policzy wszystkie potęgi od 2 do 5.
Zadanie 10.4:
Napisać program, który odwołując się do funkcji silnia (zdefiniowanej przed programem) dla wczytanej
liczby naturalnej policzy silnię.
Uwaga: W bloku funkcji może wystąpić więcej niż jedna instrukcja return (np. przy użyciu instrukcji
warunkowych)
ZMIENNE GLOBALNE
Parametr zadeklarowany na zewnątrz wszystkich funkcji występujących w danym pliku jest dostępny
wewnątrz wszystkich tych funkcji (oczywiście od linijki, w której nastąpi deklaracja).
Przykład:
#include <cstdlib>
#include <iostream>
using namespace std;
int liczba;
void f1(void) {
int x;
x = 10;
liczba ++;
cout << " w sumie = " << (x + liczba);
}
int main()
{int i;
liczba = 20;
i = 5;
cout << "Wartosci: liczba = " << liczba<< " niezmieniane i = " << i<<endl;
f1();
cout << " a teraz liczba = " <<liczba<<endl;
f1();
cout << " a teraz liczba = " <<liczba<<endl;
system("PAUSE");
return EXIT_SUCCESS;
}
PRZESYŁANIE ARGUMENTÓW PRZEZ REFERENCJE
Przekazywanie argumentów przez wartość jest tu domyślnym mechanizmem. Przy jego braku każda zmiana
wartości argumentu formalnego nie poprzedzonego modyfikatorem const wywołałaby taką samą zmianę
argumentu aktualnego. Założenie to zostało podyktowane tym, że ewentualne zmiany wartości argumentów
aktualnych, będące wynikiem wykonania jakiejś funkcji, są na ogół traktowane jako niepożądane efekty.
Natomiast w przypadku tablic jest stosowany mechanizm, który nakazuje kompilatorowi przekazanie
argumentów aktualnych w postaci adresu pierwszego elementu tablicy zamiast kopii całej tablicy.
Argumenty do funkcji możemy przesyłać nie tylko przez wartość (tak jak widzieliśmy wcześniej), ale
również przez referencje. Pozwala to funkcji na modyfikację zmiennych (nawet lokalnych) znajdujących się
poza tą funkcją.
Przykład
#include <cstdlib>
#include <iostream>
using namespace std;
void zmiana(int wartosc, int &referencja)
{
cout << "\n W funkcji 'zmiana' przed jej dokonaniem \n"
;
cout << "\n wartosc = " << wartosc << ", referencja = "
<< referencja << endl;
wartosc = -1;
referencja = -1;
cout << "\n W funkcji 'zmiana' po zmianie \n";
cout << "\n wartosc = " << wartosc << ", referencja = "
<< referencja << endl;
return;
}
int main()
{
int a = 13, b = 17;
cout << "Przed wywolaniem funkcji: 'zmiana' \n";
cout << "a = " << a << ", b = " << b << endl;
zmiana(a, b);
cout << "Po wyjsciu z funkcji: 'zmiana' \n";
cout << "a = " << a << ", b = " << b << endl;
system("PAUSE");
return EXIT_SUCCESS;
}
W przykładzie zmienna a nie uległa modyfikacji, ponieważ była przekazywana do funkcji przez wartość,
natomiast b przez referencje, zatem została zmieniona.
UWAGA: Jeśli w trakcie programu została wywołana funkcja, w ciele której znajduje się odwołanie do
kolejnej funkcji, wówczas wywołanie funkcji zawiesza wykonanie funkcji wołającej i powoduje
zapamiętanie adresu następnej instrukcji do wykonania po powrocie z funkcji wołanej. Adres ten, nazywany
adresem powrotnym, zostaje umieszczony w pamięci na stosie programu (run-time stack). Wywołana
funkcja otrzymuje wydzielony obszar pamięci na stosie programu, nazywany rekordem aktywacji lub stosem
funkcji. W rekordzie aktywacji zostają umieszczone argumenty formalne, inicjowane jawnie w deklaracji
funkcji, lub niejawnie przez wartości argumentów aktualnych.
Zadanie 10.5:
Napisać program, który pozwoli użytkownikowi na policzenie pola podstawy, pola powierzchni bocznej
oraz objętości (każda z wartości za pomocą oddzielnej funkcji) jednej z następujący brył (użytkownik musi
mieć możliwość wyboru, dla której z wymienionych brył chce wykonać obliczenia): 1. stożek, 2.
prostopadłościan z kwadratem w podstawie, 3. czworościan prawidłowy. Przy czym o podanie
odpowiednich wymiarów użytkownik musi być poproszony, aby wyprowadził je z klawiatury.
WSKAŹNIKI DO FUNKCJI
Tak jak nazwa tablicy, nazwa funkcji jest stałym wskaźnikiem.
Zatem: int f(int); oznacza deklarację funkcji f
Natomiast int (*pf) (int); oznacza deklarację wskaźnika do funkcji typu int funkcja(int)
Zaś pf = &f; oznacza, że adres f przypisany jest do pf.
Przykład
#include <cstdlib>
#include <iostream>
#include <math.h>
using namespace std;
void wypisywanie(int tab[10], int &n)
{
cout<<"podaj ilosc elementow tablicy "; cin>>n;
for (int i=1; i<=n; i++)
{
cout <<"element tablicy nr "<<i<<"= "; cin >>tab[i];
}
}
void wariancja(int tab[10], int &n, float &war)
{
float sr=0;
for (int i=1; i<=n; i++)
sr+=tab[i];
sr/=n;
war=0;
for (int i=1; i<=n; i++)
war=war+(tab[i]-sr)*(tab[i]-sr);
war=sqrt(war/n);
}
int main()
{int n,tab[10];
float war;
wypisywanie(tab,n);
wariancja(tab,n,war);
cout <<"wariancja dla podanej tablicy= "<<war<<endl;
system("PAUSE");
return EXIT_SUCCESS;
}
Klasy w C++
Klasa jest kluczową koncepcją języka C++, realizującą abstrakcję danych na bardzo wysokim poziomie.
Odpowiednio zdefiniowane klasy stawiają do dyspozycji użytkownika wszystkie istotne mechanizmy
programowania obiektowego: ukrywanie informacji, dziedziczenie, polimorfizm z wiązaniem późnym, a
także szablony klas i funkcji. Klasa jest deklarowana i definiowana z jednym z trzech słów kluczowych:
class, struct i union.
Elementami składowymi klasy mogą być struktury danych różnych typów, zarówno podstawowych, jak i
zdefiniowanych przez użytkownika, a także funkcje dla operowania na tych strukturach. Dostęp do
elementów klasy określa zbiór reguł dostępu.
Klasa jest typem definiowanym przez użytkownika. Deklaracja klasy składa się z nagłówka, po którym
następuje ciało klasy, ujęte w parę nawiasów klamrowych; po zamykającym nawiasie klamrowym musi
wystąpić średnik, ewentualnie poprzedzony listą zmiennych. W nagłówku klasy umieszcza się słowo
kluczowe class (lub struct albo union), a po nim nazwę klasy, która od tej chwili staje się nazwą nowego
typu.
Klasa może być deklarowana:
−
Na zewnątrz wszystkich funkcji programu. Zakres widzialności takiej klasy rozciąga się na wszystkie pliki
programu.
−
Wewnątrz definicji funkcji. Klasę taką nazywa się lokalną, ponieważ jej zakres widzialności nie wykracza
poza zasięg funkcji.
−
Wewnątrz innej klasy. Klasę taką nazywa się zagnieżdżoną, ponieważ jej zakres widzialności nie wykracza
poza zasięg klasy zewnętrznej.
Deklaracji klas nie wolno poprzedzać słowem kluczowym static.
Przykładowe deklaracje klas mogą mieć postać:
class Pusta {};
class Komentarz { /* Komentarz */};
class Niewielka { int n; };
•Wystąpienia klasy deklaruje się tak samo, jak zmienne innych
typów, np.
Pusta pusta1, pusta2;
Niewielka nw1, nw2;
Niewielka* wsk = &nw1;
Zmienne
pusta1
,
pusta2
,
nw1
,
nw2
nazywają się obiektami, zaś
wsk
jest wskaźnikiem do typu
Niewielka
, zainicjowanym adresem obiektu
nw1
.
Klasy w rodzaju
Pusta
i
Komentarz
używa się często jako klasy-makiety podczas opracowywania
programu.
Deklaracje elementów składowych klasy można poprzedzić etykietą public:, protected:, lub private:. Jeżeli
sekwencja deklaracji elementów składowych nie jest poprzedzona żadną z tych etykiet, to kompilator
przyjmuje domyślną etykietę private:. Oznacza to, że dana składowa może być dostępna jedynie dla funkcji
składowych i tzw. funkcji zaprzyjaźnionych klasy, w której jest zadeklarowana. Wystąpienie etykiety
public: oznacza, że występujące po niej nazwy deklarowanych składowych mogą być używane przez
dowolne funkcje, a więc również takie, które nie są związane z deklaracją danej klasy. Znaczenie etykiety
protected: - później.
Ze względu na sterowanie dostępem do składowych klasy, słowa kluczowe public, protected i private
nazywa się specyfikatorami dostępu.
#include <cstdlib>
#include <iostream>
using namespace std;
class Pierwsza_klasa {
public:
int n;
};
int main()
{
Pierwsza_klasa nw1, nw2, *wsk;
nw1.n = 5;
nw2.n = 10;
wsk = &nw1;
cout << nw1.n << endl; //do zmiennej obiektowej
cout << wsk->n << endl; //do zmiennej wskaźnikowej
wsk = &nw2;
cout << (*wsk).n << endl;
system("PAUSE");
return EXIT_SUCCESS;
}