Przekazywanie argumentów przez referencję i przeciążanie funkcji
Przekazywanie argumentów przez referencję
W języku C++ funkcje domyślnie kopiują pojedyncze zmienne na czas wywołania funkcji. W momencie zakończenia funkcji, kopie te są usuwane z pamięci. Aby móc operować na oryginalnych zmiennych, np. wczytywać do nich dane, musimy zawrzeć znak & (czyt. ampersand) przed nazwą zmiennej, w nagłówku funkcji np. void WczytajDane(int& a, char& b)
Nie jest to konieczne przy operowaniu na tablicachtablicach. Ponieważ gdy przekazujemy tablicę do funkcji, jednocześnie przekazujemy adres pierwszego elementu w tej tablicy. Tablice nie są kopiowane na potrzeby funkcji, ponieważ byłoby to zbyt czasochłonne, a sam proces zajmowałby dużo pamięci.
W naszym przypadku, aby wczytane wartości były zapisane do oryginalnych zmiennych przy wywołaniu funkcji, musimy zapisać znak & przed każdą nazwą zmiennej. Nagłówek funkcji powinien być zapisany w następujący sposób:void WczytajDane(int& a, int& b, int& c, int& d, int& e, int& f)
Różne funkcje o tych samych nazwach
Warto wspomnieć, że w języku C++ kilka funkcji może mieć te same nazwy. Jednak wywoływana będzie ta funkcja, która ma odpowiednie typy argumentów.
W przedstawionym programie mamy zapisane dwie funkcje WczytajDane(). Jedna z nich jako parametr ma podaną referencję do zmiennej typu int, natomiast druga jako parametr ma podaną referencję do zmiennej typu char. W momencie wywołania funkcji WczytajDane() w naszej funkcji main kompilator wie, której funkcji musi użyć na podstawie podanych jej argumentów. W przypadku wywołania funkcji WczytajDane() dla zmiennej a zostanie wywołana ta funkcja, która jako parametr ma podaną referencję do zmiennej typu int. Natomiast w momencie wywołania funkcji WczytajDane() dla zmiennej b zostanie wywołana ta funkcja, której parametr jest typu char.
Występowanie co najmniej dwóch funkcji o takiej samej nazwie nazywamy przeciążaniem funkcji. W przypadku wywołania takich funkcji mogą pojawić się sytuacje niejednoznaczne lub błędy, ponieważ nie zawsze kompilator jest w stanie odpowiednio odróżnić funkcje o tej samej nazwie. W celu uniknięcia tych problemów warto rozróżniać funkcje, nadając im niejednakowe nazwy.
Program obliczający, ile jest liczb pierwszych w przedziale
Nasz program będzie pobierał od użytkownika liczbę, a następnie sprawdzał czy kolejne liczby (począwszy od dwójki, a kończąc na liczbie x) są pierwsze. Wynikiem programu będzie informacja, ile z napotkanych liczb było pierwszymi. Zaproponowane rozwiązanie wyznaczania liczb pierwszych z zadanego zakresu jest rozwiązaniem alternatywnym do tego, które przedstawiliśmy w innym materiale dotyczącym algorytmu - Sito Eratostenesa. Nie wymaga użycia dodatkowych struktur danych - tablic, dzięki czemu zyskujemy więcej pamięci, kosztem wydajności. Po przeanalizowaniu implementacji, spróbuj samodzielnie zaimplementować algorytm Sito Eratostenesa w języku C++, z zastosowaniem funkcji.
Specyfikacja problemu:
Dane:
x– koniec przedziału, w którym będą poszukiwane liczby pierwsze; liczba naturalna > 2
Wynik:
Program na standardowym wyjściu drukuje liczbę liczb pierwszych w przedziale
Krok 1.
Zapisz szkielet naszego programu.
Krok 2.
Zapisz nagłówek funkcji wczytującej dane wraz z klamrami obejmującymi ciało funkcji.
W nagłówku funkcji zapisujemy znak & przy każdej zmiennej. Ponieważ wczytujemy dane do tej zmiennej, potrzebujemy dostępu do oryginału. Funkcja WczytajDane() jest funkcją typu void, ponieważ pozwala wczytać dane, a nie zwraca żadnych wartości.
Krok 3. Wypełnij ciało funkcji WczytajDane().
Krok 4. W funkcji main() zadeklaruj odpowiednią zmienną, a następnie wczytaj do niej dane za pomocą wcześniej utworzonej funkcji.
Krok 5. Zapisz funkcję sprawdzającą, czy dana liczba jest liczbą pierwszą.
Nasza funkcja jest typu bool, ponieważ zwraca true, jeśli liczba jest liczbą pierwszą oraz false, jeśli liczba nie jest liczbą pierwszą. Funkcja ma jeden parametr typu int, następnie w pętli, dla sprawdzane jest, czy nasza liczba dzieli się bez reszty przez i. Jeśli tak – liczba nie jest pierwsza. Zatem zwracamy wartość false. Jeśli w trakcie działania pętli nie znajdziemy dzielnika a – oznacza to, że jest to liczba pierwsza. Możemy więc zwrócić true.
Funkcja sqrt() dostępna jest w bibliotece cmath – pamiętaj, by ją dołączyć w programie.
Krok 6. Zadeklarujmy zmienną, która będzie przechowywać liczbę wszystkich liczb pierwszych. Od razu wyzerujmy jej wartość.
Krok 7. Zapiszmy pętlę for, która będzie się wykonywała od 2 do x, a w niej sprawdźmy – przy pomocy wcześniej zapisanej funkcji – (pamiętając o dołączeniu biblioteki cmath) czy liczba jest liczbą pierwszą. Jeśli tak jest, zwiększmy wartość zmiennej pierwszych o jeden.
Krok 8. Wypiszmy wartość zmiennej pierwszych wraz z odpowiednim komunikatem.
Domyślnie funkcje w C++ pracują na kopiach argumentów.
Oryginalne zmienne pozostają niezmienione po zakończeniu funkcji.Aby funkcja mogła modyfikować zmienne przekazane z zewnątrz, używamy referencji, czyli dodajemy znak & w nagłówku funkcji:
void WczytajDane(int& a, char& b);Tablice nie są kopiowane przy przekazywaniu do funkcji.
Przekazywany jest adres pierwszego elementu, więc funkcja operuje na oryginalnych danych.Referencję stosujemy wtedy, gdy chcemy zmienić wartości zmiennych wywołujących funkcję.
C++ pozwala na istnienie wielu funkcji o tej samej nazwie, o ile różnią się typami lub liczbą argumentów. Mechanizm ten nazywa się przeciążaniem funkcji.
Słownik
układ liczb, symboli lub wyrażeń zapisanych w postaci tablicy, w rzędach i kolumnach
metoda, która polega na rozwiązywaniu układu równań za pomocą wyznaczników