C++/Przeciążanie operatorów: Różnice pomiędzy wersjami

Usunięta treść Dodana treść
DrJolo (dyskusja | edycje)
m →‎Przykład zastosowania: drobne techniczne
Linia 19:
Mamy daną klasę Student
 
<source lang="cpp">
'''class''' Student
{
'''int''' nr_indeksu;
'''float''' srednia_ocen;
'''public''':
Student('''int''' nr=0, '''float''' sr=0) {nr_indeksu=nr; srednia_ocen=sr;} // konstruktor
};
</source>
 
i chcemy przeładować operator wyjścia <<
Linia 32 ⟶ 34:
Robimy to w następujący sposób:
 
<source lang="cpp">
'''class''' Student
{
'''int''' nr_indeksu;
'''float''' srednia_ocen;
'''public''':
Student('''int''' nr=0, '''float''' sr=0) {nr_indeksu=nr; srednia_ocen=sr;} // konstruktor
'''friend''' ostream & '''operator'''<< (ostream &wyjscie, '''const''' Student &s);
};
ostream & '''operator'''<< (ostream &wyjscie, '''const''' Student &s)
{
wyjscie << "Nr indeksu : " <<s.nr_indeksu << endl << "Srednia ocen : " <<s.srednia_ocen<<endl;
'''return''' wyjscie;
}
</source>
 
 
Aby zobaczyć, jak to działa, wystarczy że funkcja <tt>main()</tt> będzie miała następującą postać:
 
<source lang="cpp">
'''int''' main()
{
Linia 59 ⟶ 63:
cout << stu; // wypisze nr indexu = 10, srednia ocen=5
'''return''' 0;
}
</source>
 
W powyższym przykładzie wprowadzone zostało także nowe pojęcie - zaprzyjaźnianie (''friend''). Funkcję F() deklarujemy jako zaprzyjaźnioną z klasą X, jeśli chcemy, aby F() miała dostęp do prywatnych lub chronionych danych składowych klasy X.
Linia 66 ⟶ 71:
Ale weźmy przykład nieco prostszy. Chcemy sprawdzić czy to jest ten sam student - przeciążamy operator:
 
<source lang="cpp">
'''class''' Student
{
//...
'''public''':
'''int''' '''operator'''==(Student &q) {'''return''' nr_indeksu==q.nr_indeksu};
'''int''' '''operator'''==('''int''' &q) {'''return''' nr_indeksu==q};
};
</source>
I niby wszystko jest pięknie, ale tu zacznają się schody... My, jako twórcy klasy wiemy, że porównanie dotyczy się tylko i wyłącznie numeru indeksu. Przy różnych średnich i tych samych indeksach dostaniemy wynik pozytywny. A nuż niech ktoś sobie ubzdura, że == odnosi się do wszystkich składowych...
Linia 78 ⟶ 85:
Dalsze zamieszanie wprowadzą kolejne zaproponowane przeze mnie operatory.
 
<source lang="cpp">
'''class''' Student
{
//...
'''public''':
'''int''' '''operator'''< ( Student &q) {'''return''' srednia < q.srednia};
'''int''' '''operator'''< ('''int''' &q) {'''return''' srednia < q};
// itd dla kolejnych operatorów.
};
</source>
 
Samo w sobie nie jest groźne. Dopiero przy konfrontacji z poprzednim operatorem zaczyna wprowadzać zamieszanie. Wszystko jest dobrze kiedy pamiętamy, jakie operacje dane operatory wykonują. '''Ale pamiętajmy: pamięć ludzka jest ulotna i ktoś inny (albo my) może spędzić kilka dni zanim dojdzie do tego, dlaczego to działa nie tak jak powinno.'''
Linia 91 ⟶ 100:
Ale powyższy przykład wygląda naprawdę blado w porównaniu z tym:
 
<source lang="cpp">
 
'''class''' Student
{
//...
'''public''':
'''int''' '''operator'''+ ( Student &q) {'''return''' (srednia + q.srednia +11) };
'''int''' '''operator'''+ ( '''int''' &q) {'''return''' (srednia - q / 30) };
};
</source>
 
Jak widzicie operator '''+''' wcale nas nie zmusza do wykonywania operacji dodawania. Możemy równie dobrze wewnątrz odejmować. A przy odejmowaniu porównywać. Lecz takie postępowanie nie jest intuicyjne. Takie postępowanie jest dozwolone jedynie w przypadkach, kiedy startujecie w [[wikipedia:International Obfuscated C Code Contest|konkursie na najbardziej nieczytelny kod]].