background image

Ć

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> 
 

background image

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; 

background image

 
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;  

 

 

 

 

 

 

 

 

 

  

background image

 

 

 

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; 

 

background image

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. 

background image

 
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; 

background image

    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: 
classstruct 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. 

background image

 
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; 

background image

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; 
}; 
 

background image

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;