przeciążanie operatorów
DESCRIPTION
Przeciążanie operatorów. Na czym to polega ?. Krótko mówiąc, aby zmusić znaczki typu: +,- itd. Aby robiły to co im każemy. Kluczem do zrozumienia pisania operatorów jest fakt abyśmy uświadomili sobie, że sami możemy napisać funkcję "operatora dodawania", która będzie - PowerPoint PPT PresentationTRANSCRIPT
Przeciążanie operatorów
Krótko mówiąc, aby zmusić znaczki typu:+,- itd. Aby robiły to co im każemy.
Kluczem do zrozumienia pisania operatorów jest fakt abyśmy uświadomili sobie, że sami możemy napisać funkcję "operatora dodawania", która będziewywoływana wtedy, gdy obok znaczka + pojawią się argumenty wybranego przez nas typu. W tym momenciezostanie przeładowany operator +.
Na czym to polega ?
Przeciążanie operatorów
Czym specjalnym wyróżnia sie taka funkcja?
NICZYM, poza nazwą, która musi przyjąć postać operatorX, gdzie X oznacza wybrany przez nas operator (np.: +,-,/,*). Poza tym jest to najzwyklejsza w świecie funkcja, która o dziwo wcale nie musi dodawać, odejmować itd. , może po prostu zagwizdać naszym głośniczkiem w komputerze.
Kluczowym elementem jest to, że kiedy kolo obiektu naszej klasy pojawi się znak + to funkcja zostanie
uruchomiona automatycznie!
obiekt1 + obiekt2 Można również wywołać ją jak zwykłą funkcję
operator+(obiekt1,obiekt2)
Przeciążanie operatorów
• Przykład:• Rozważmy klasę która opisuje współrzędne punktów:
• class wsp{• public:• float osX;• float osY;
• wsp operator+(wsp a,wsp b){• wsp suma;• suma.osX = a.osX + b.osX;• suma.osY = a.osX + b.osY;• return suma;• }• };
Ten przykład obrazuje w jaki sposób możemy przeciążyć operator ‘’+’’ lub jakikolwiek inny.
Przeciążanie operatorów
Wiemy już zatem, że można przeładować operator +. Nasuwa się pytanie kiedy to robić? Oczywiście w sytuacji, gdy wobec obiektu danej klasy bardziej naturalne wydaj się używać znaku + niż wywołanie funkcji. Jest to moment, w którym powinniśmy rozważyć możliwość przeładowania. Często się tak dzieje wobec klas powiązanych z matematyka .Lecz niekoniecznie, można przecież napisać:
ekran + okno
w celu ujrzenia na ekranie okienka.
Przeciążanie operatorów
//Manipulowanie łańcuchami w c:
char napis[10];napis = „Tekst”; //błądstrcpy(napis, „Tekst”); //poprawnie
Operator przypisania „=”
Przeciążanie operatorów//Wersja w C++:
string napis;napis = „Tekst”;//poprawnie, gdyż w klasie string przeciążony //został operator przypisania „=”
Przeciążanie operatorów jest techniką mającą głównie na celu zwiększenie czytelności programu i ułatwienie manipulowania obiektami.
class Napis{
private:char bufor[100];
public:Napis &operator=(const char* str);void set(const char* str) {strcpy(bufor, str);}const char *get() {return bufor;}
};
Napis &Napis::operator=(const char* str){
set(str);return *this;
}
int main(int argc, char *argv[]){
Napis napis;
napis = "PO to nasz ulubiony przedmiot:)";cout << napis.get();
return 0;}
Przykład przeciążenia operatora przypisania „=”
class Napis{
private:char bufor[100];
public:Napis &operator=(const char* str);char operator[](int i) {return bufor[i];}void set(const char* str) {strcpy(bufor, str);}const char *get() {return bufor;}
};
Napis &Napis::operator=(const char* str){
set(str);return *this;
}
int main(int argc, char *argv[]){
Napis napis;napis = "PO to nasz ulubiony przedmiot:)";for (int i = 0; i < 10; ++i)
cout << napis[i]; return 0;}
Przykład przeciążenia operatora indeksowania „[ ]”
Przeciążanie operatorówUwagi:
1.Przeładowywać można tylko powyżej podane operatory, nie można wymyślać swoich.
2.Przeładowanie może nadać operatorowi dowolne znaczenie, nie ma też ograniczeń co do wartości zwracanej przez operator(wyjatki to: new i delete).
3.Nie można jednak zmienić priorytetu wykonywania tych operatorów.na przykład:Wyrażeniea+b*czawsze będzie wykonywane jako a+(b*c)a nie jako(a+b)*c
Przeciążanie operatorów4.Nie można zmienić argumentowości operatorów, czyli tego czy operator jest jedno czy dwu argumentowy. Przykładowo: operator / (mnożenie) zawsze będzie dwu argumentowy.
przykład: element1 / element2 //dobrze!
element1 / element2/ //źle
Tak samo z operatorem ! (negacji) , jest jedno argumentowy.Nie możemy wiec napisać
element1 ! element2 // źle
!element1 // dobrze5. A oto lista operatorów które można przeciążać:
+ - * / % ^ & | - ! = < > += -= /= %= ^= &= |= <<>> >>= <<= == != <= >= && || ++ -- , ->* -> () []
Przyjaźń. Funkcje i Klasy zaprzyjaźnione.
Relacje przyjaźni są to stosunkowo niedawno dodane
właściwości C++.
Funkcje zaprzyjaźnione nie są jedynymi rodzajami form zaprzyjaźnionych jakie może posiadać klasa. Sama klasa również może być zaprzyjaźniona.
W takim przypadku każda metoda klasy
zaprzyjaźnionej ma dostęp do prywatnych
chronionych składowych klasy oryginalnej.
• To klasa definiuje jakie funkcje, metody lub inne klasy są w stosunku do niej formami zaprzyjaźnionymi.
• Relacje „przyjaźnienia się” nie mogą być narzucane z zewnątrz do prywatnych składowych klasy, w rzeczywistości nie naruszają one żadnych idei programowania obiektowego.
• Głównym celem, „przyjaźnienia się” jest uelastycznienie interfejsu publicznego.
• Po co chcieć zaprzyjaźnić jakąś klasę z inną ?
Popatrzmy na przykład.
• Class Tv {
public: friend class Pilot ; // Klasa Pilot ma dostęp do części prywatnej klasy TV
void onOff (void){ // instrukcje } void metoda(void ){ //instrukcje } private:
int stan ; int glosnosc; int wejscie;
int ustawKanal(int kanal) { } }
• Class Pilot {private :
int tryb ;public : bool glosniej (Tv & t) { return t.glosniej(); } bool ciszej (Tv & t) { return t.ciszej();} void onOff (Tv & t) { t.onOff(); }
void ustaw() {ustawKanal(int kanal);} };
Uwaga :
Każda z metod klasy Pilot pobiera jako argument referencje doobiektu Tv - jest to odzwierciedlenie faktu skojarzenia pilota z określonym telewizorem.
• Funkcje zaprzyjaźnioneNiezależne funkcje zaprzyjaźnione mają dostęp do składowych prywatnych i chronionych klasy. Sama funkcja nie nabywa własności składowej klasy.
class Punkt{
static int ile_punktow; float x, y;
public:friend void wyswietl(punkt&); // deklaracje friendfriend void wyswietl(punkt*);friend void wyswietl(punkt, char); friend void wyswietl();
};
void wyswietl(punkt& p)
{
cout<<”Przekazanie przez referencje punktu o “;
cout <<”wspolrzednych: “ << p.y << “ “<< p.y << “\n”; getch();
}
void wyswietl(punkt *p)
{
ciało funkcji bez hermetyzacji obiektu p
}
void wyswietl(punkt p, char)
{
ciało funkcji bez hermetyzacji obiektu p
}
void wyswietl()
{
cout <<"Liczba punktow: " << punkt::ile_punktow << "\n";
}
• Funkcje zaprzyjaźnione z wieloma klasamiNiezależna funkcja zaprzyjaźniona z kilkoma klasami ma dostęp do wszystkich składowych prywatnych i chronionych tych klas. Sama funkcja nie nabywa jednak własności składowej tych klas. Deklaracja zaprzyjaźnienia powinna wystąpić w każdej z tych klas, natomiast definicja tylko raz .
class Kolo; // niezbędna deklaracja klasy kolo ze względu na deklarację friend
class Punkt{ static int ile_punktow;
float x, y; public:
friend void wyswietl(kolo&); // deklaracja friend}; class Kolo { static int ile_kol; float promien; punkt srodek; public:
friend void wyswietl(kolo&);}; // deklaracja friend
• Język C++ dopuszcza również możliwość wskazania poszczególnych składowych klasy, które mają być zaprzyjaźnione lecz, jest to trochę kłopotliwe.
• W takiej sytuacji powinniśmy pamiętać o zachowaniu odpowiedniej kolejności w jakiej pojawiają się różne deklaracje i definicje.
Dzięki zaprzyjaźnieniu do wyświetlenia utworzono jedną funkcje wyświetl. W ciele funkcji są dostępne wszystkie składowe klas kolo i punkt
• Przykład :Chcąc zaprzyjaźnić metodę Pilot :: ustaw kanał () z klasą Tv należy zadeklarować ją z przedrostkiem friend i umieścić w sekcji deklaracyjnej klasy Tv
class Tv {friend Pilot :: ustaw kanał (Tv &t )}
• Jednakże aby kompilator mógł przetworzyć taką instrukcję, wcześniej musi do definicji klasy Pilot. W przeciwnym wypadku nie będzie wiedział, że Pilot jest klasą a ustawkanal() metodą tej klasy. Jednak metody klasy Pilot odwołują się do klasy Tv.
• W tym celu przed definicją klasy Pilot trzeba umieścić „zapowiedź” klasy Tv
class Tv ; // deklaracja zapowiadającaclass Pilot {….};class Tv {…..};