• Nie Znaleziono Wyników

Przeciążanie nazw funkcji i przeciążanie operatorów

N/A
N/A
Protected

Academic year: 2021

Share "Przeciążanie nazw funkcji i przeciążanie operatorów"

Copied!
5
0
0

Pełen tekst

(1)

Programowanie w C++

Lab 9

Przeciążanie nazw funkcji i przeciążanie operatorów

1. Przeciążanie nazw funkcji

W języku C++ można zdefiniować więcej niż jedną funkcję o tej samej nazwie. Nazywa się to przeciążaniem nazw funkcji (lub w skrócie przeciążaniem funkcji). Dzięki temu funkcja o jednej nazwie może obsługiwać różne typy danych. Aby kod programu się skompilował, funkcje muszą się różnić typem oraz ewentualnie ilością argumentów wejściowych. Na tej podstawie kompilator rozróżnia, którą implementację funkcji zastosować dla danego jej wywołania w programie.

Przykład 1. Program ma trzy przeciążone funkcje o nazwie wyswietl( argument ), gdzie do funkcji jako argument możemy przekazać liczbę całkowitą (typu int), liczbę rzeczywistą (typu float) lub nawet własny typ danych typu punkt – wówczas wyświetlone zostaną obie współrzędne punktu.

W zależności od przekazanego argumentu zostanie uruchomiona odpowiednia funkcja.

Cały program:

#include <iostream>

using namespace std;

// definicja własnej struktury typu punkt // przechowuje współrzędne x i y

struct punkt {

float x, y;

};

// przeciążona funkcja wyswietl dla typu int void wyswietl(int liczba)

{

cout << "liczba typu int: " << liczba << endl;

}

// przeciążona funkcja wyswietl dla typu float void wyswietl(float liczba)

{

cout << "liczba typu float: " << liczba << endl;

}

// przeciążona funkcja wyswietl dla typu punkt void wyswietl(punkt a)

{

cout << "x: " << a.x << "\t y:" << a.y << endl;

}

int main() {

float jakas_liczba = 5.342;

int liczba_calkowita = 3;

wyswietl(jakas_liczba); // wywolanie funcji wyswietl ze zmienną typu float wyswietl(liczba_calkowita); // wywolanie funcji wyswietl ze zmienną typu int

// tworzymy dwa punkty i określamy ich współrzędne

(2)

punkt P1 = {5,4};

punkt P2 = {10,10};

// wywolujemy funkcje wyswietl dla typu punkt dla obu punktow wyswietl(P1);

wyswietl(P2);

return 0;

}

2. Przeciążanie operatorów

Przeciążanie operatorów umożliwia definiowanie działań dla własnych typów danych (struktur, obiektów) oraz na zmianę działania operatorów da wbudowanych typów (takich jak int, float, char itd.). Na razie zajmiemy się programowaniem przykładowych działań dla własnego typu. W poniższym przykładowym programie:

1) Stworzymy nowy typ wektor. Będzie to dwuwymiarowy wektor zaczepiony w początku układu współrzędnych i końcu określonym przez parę punktów x i y.

2) Przeciążymy operator przypisania = , dzięki czemu będzie można przypisać współrzędne z jednego wektora (lub działania którego wynikiem jest wektor) do innego wektora, np.

wektor w1(5, 7); // tworzymy wektor w1 o wsp. x = 5 i y = 7 wektor w2 = w1; // tworzymy wektor w2 i przypisujemy mu

// współrzędne wektora w1;

Bez przeciążania znaku = nie moglibyśmy zapisać w2 = w1. Przypisanie musielibyśmy zrealizować np. tak:

w1.x = w2.x;

w1.y = w2.y;

Jeśli mielibyśmy 10 składowych w strukturze, to wtedy mielibyśmy też 10 instrukcji

przypisania poszczególnych składowych. Kod programu niepotrzebnie się wydłuża jak i łatwo o pomyłkę. Dzięki przeciążeniom operatorów można wszystko zrealizować jedną instrukcją.

3) Przeciążymy operator dodawania + , który pozwoli na dodawanie wektorów, np.

wektor w1(5, 7), // tworzymy wektor w1 i w2 z określonymi w2(2, 2); // współrzędnymi

wektor w3 = w1 + w2; // obliczamy sumę wektorów w1 i w2 i wynik // zapisujemy do nowego wektora w3

4) Przeciążymy operator porównania == , który pozwoli na sprawdzenie, czy dwa wektory mają te same współrzędne, np.

bool czy_rowne = (w1 == w2) // wyrażenie w1 == w2 zwróci wartość // true jeśli wektory będą miały jednakowe współrzędne

5) Przeciążymy operator *, co pozwoli na skalowanie wektora, np.

wektor w1(10, 5);

wektor w2 = w1*2.5; // wektor w2 będzie miał współrzędne 25, 12.5

Cały program:

(3)

/*

Program definiuje nowy typ wektor i przeciąża dla niego operator przypisania =, dodawania +, porównania == oraz mnożenia *.

Uwaga dot. nazewnictwa (na przykładzie działania dodawania):

operator | w1 + w2 | | lewy prawy operand operand

*/

#include <iostream>

using namespace std;

// definicja nowego typu wektor za pomocą stuktury struct wektor

{

float x;

float y;

// konstruktor i wartości domyślne

// umożliwia utworzenie i zainicjowanie zmiennej w postaci np. wektor = P(5, 10);

wektor(float a=0, float b=0) {

x = a;

y = b;

}

// przeciążanie operatorów w implementacji struktury:

// składnia: zwracany_typ operator# = (operand z prawej strony)

// # - jeden z operatorów języka C++, np. +, -, /, *, %, ^, ==, !=, itd.

// można dodać const jeśli operand ma nie być modyfikowany

// korzystamy przy tym z referencji (&) aby nie tworzyć niepotrzebnie // kopii prawego operandu w pamięci

// przeciążenie operatora =

// przepisuje wsp. z wektora a do aktualnego wektora.

// Wektor a jest tym, co pojawi się z prawej stronypodczas użycia operatora = // (lewy operand)

wektor operator=(const wektor &a) {

x=a.x;

y=a.y;

}

// przeciążenie operatora +

// dodaje wspołrzędne wektora z lewej strony znaku + (lewy operand) // oraz wekroa z prawej strony znaku + (prawy operand)

// Zwraca nowy wektor

wektor operator+(const wektor &a) const {

return wektor(x+a.x, y+a.y);

}

// przeciążenie operatora porównania ==

// Zwraca wartość logiczną prawda, jeżeli składowe // porównywanych wektorów są jednakowe

bool operator==(const wektor &a) const {

return (x == a.x && y == a.y);

}

(4)

// przeciążony operator mnożenia * // Mnoży współżędne wektora przez skalę wektor operator*(const float &skala) {

return wektor(x*skala, y*skala);

} };

int main() {

// utworzenie zmiennych typu wektor: P1 i P2 // oraz zainicjowanie ich współrzędnych wektor W1(3, 4);

wektor W2(2, 5);

// --- cout << "Wspolrzedne wektora W1: " << endl;

cout << W1.x << " " << W1.y << endl;

cout << "Wspolrzedne wektora W2: " << endl;

cout << W2.x << " " << W2.y << endl;

// --- // wykorzystanie operatora sumy + oraz przypisania = wektor W3 = W1+W2;

cout << "Wspolrzedne wektora W3 = W1 + W2: " << endl;

cout << W3.x << " " << W3.y << endl;

// --- // wykorzystanie przeciążonego operatora * wektor W4 = W3*0.5;

cout << "\nSkaluje wektor W3 o wspolczynnik 0.5." << endl;

cout << "Wspolrzedne nowego wektora W4:" << endl;

cout << W4.x << " " << W4.y << endl << endl;

// --- // sprawdzenie działania operatora ==

if (W2 == W3)

cout << "wektory W2 i W2 maja jednakowe wspolrzedne.";

else

cout << "wektory W2 i W3 maja rozne wspolrzedne.";

return 0;

}

Zad 1.

Zmodyfikuj program z przykładu 1:

a) Struktura punkt niech przechowuje również trzecią współrzędną, a wywołanie funkcji wyświetl dla punktu powoduje wyświetlenie wszystkich współrzędnych na ekranie.

b) Zdefiniuj pięcioelementową tablicę elementów typu całkowitoliczbowego. Dopisz czwartą przeciążoną funkcję wyswietl, która jako argument przyjmuje tablicę i liczbę jej elementów.

Niech elementy wyświetlają się w jednej linii oddzielone spacją.

Zad 2.

(5)

Dodaj do programu z przykładu 2:

a) przeciążenie operatora odejmowania umożliwiającego odejmowanie od siebie współrzędnych punktów,

b) drugie przeciążenie operatora * umożliwiające obliczanie iloczynu skalarnego wektorów.

Zwróć uwagę na drugi operand, jaki powinna przyjmować kolejna (czyli przeciążona) funkcja przeciążenia operatora * oraz na zwracany typ.

Zad 3.

Zmodyfikuj program z poprzedniego zadania, aby umożliwiał operacje na wektorach w trzech wymiarach. Do wyświetlania współrzędnych wektora napisz własną funkcję.

Zad 4.

Zmodyfikuj operator porównania == aby sprawdzał, czy wektory są jednakowej długości (zamiast sprawdzania, czy mają jednakowe współrzędne).

Cytaty

Powiązane dokumenty

Gdy pole statyczne jest zdefiniowane wewnątrz metody danej klasy możemy odwołać się do niego przy pomocy jego nazwy.. Nazwy tej nie można jednak poprzedzić słowem

Wydział Informatyki, Elektrotechniki i Telekomunikacji Instytut Sterowania i Systemów Informatycznych. Informatyka stacjonarne-dzienne pierwszego stopnia z

 Klauzula NOT EXISTS jest wykorzystywana do znajdowania wierszy, dla których powiązane podzapytanie nie zwraca żadnych wartości.  Przydaje sie to do znajdowania wierszy,

Niezależna funkcja zaprzyjaźniona z kilkoma klasami ma dostęp do wszystkich składowych prywatnych i chronionych tych klas3. Sama funkcja nie nabywa

Ponieważ programiści oczekują, że operacja przypisania dla dwóch zmiennych jednakowego typu zawsze powinna się powieść, dlatego kompilator zawsze automatycznie tworzy ten

Skutecz- ność działania operatora systemu można także oceniać przez pryzmat jakości realizowanych zadań przez system jako całość.. Przedmiotem ergonomii jest

Dopisz i wykorzystaj w programie metodę Spaceruj( double godziny ), która ma robić to samo, co metoda jednoparametrowa Spaceruj( int minuty ), ale komunikat o

Napisz zaprzyjaźnioną z klasą Zespolona metodę przeciążającą operator &lt;&lt; tak, aby było możliwe wypisanie na ekran wartości liczby zespolonej np3. Deklaracja w klasie