Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Nie rozumiem mechanizmu przeładowania operatorów

Ostatnio zmodyfikowano 2014-04-11 07:33
Autor Wiadomość
Orb
Temat założony przez niniejszego użytkownika
Nie rozumiem mechanizmu przeładowania operatorów
» 2014-04-11 03:34:12
Wcześniej pytałem o to na innym forum, ale nie dostałem żadnej odpowiedzi, więc pozwolę sobie wkleić żywcem, co by jeszcze raz się nie produkować. Trochę się rozpisałem, ale głównie chodzi mi o wytknięcie błędów w sposobie myślenia, dlatego streściłem sposób w jaki główkowałem.

Wygląda na to, że poprzednie pytanie było za głupie, żeby ktoś odpowiedział. Teraz więc dręczy mnie inna rozkmina. Uczę się przeładowywać operatory na podstawie kursu z wiki: http://pl.wikibooks.org/wiki​/C%2B%2B​/Przeci%C4%85%C5%BCanie_operat​or%C3%B3w]C++​/Przeciążanie operatorów - Wikibooks, biblioteka wolnych podręczników

Pierwszy przykład niby zrozumiałem. Wykonałem coś podobnego tylko w inny sposób. Skompilowało się i działało. W drugim (rzekomo prostszym) przykładzie coś mi nie gra. Siedzę nad przykładem przeładowania:
C/C++
class Student
{
    //...
public:
    int operator ==( const Student & q ) { return nr_indeksu == q.nr_indeksu; }
    int operator ==( const int & q ) { return nr_indeksu == q; }
};

Pierwsza funkcja jeśli dobrze rozumiem ma za zadanie umożliwić porównanie dwóch instancji klasy student pod względem indeksu. Pierwsze, co przyszło mi na myśl to czy nie da się porównać bez przeciążania. Oczywiście zakładałem, że jeśli zadziała, to będzie sprawdzało czy obiekty są identycznie. Kompilator stwierdził, że "==" nie wie co operator ma robić z obiektem tej klasy. Nie zdziwiłem się, bo niby po co autor kursu miałby podawać przykład, który prościej jest zrobić bez prezentowanego narzędzia. Mimo to zawsze sprawdzam kiedy się czegoś uczę, czy aby na pewno to potrzebne. Dlatego mniej więcej kumając pierwszą funkcje przeładowania napisałem szybki kod wykorzystujący go w prosty sposób:
C/C++
#include <iostream>
#include <string>

using namespace std;

class Student
{
    int nr_indeksu;
    float srednia_ocen;
public:
    Student( int nr = 0, float sr = 0 )
        : nr_indeksu( nr )
        , srednia_ocen( sr )
    {
    }
    friend ostream & operator <<( ostream & wyjscie, const Student & s )
    {
        return wyjscie << "Nr Indeksu: " << s.nr_indeksu << endl << "Średnia Ocen: " << s.srednia_ocen << endl;
    }
    int operator ==( const Student & q ) { return nr_indeksu == q.nr_indeksu; }
};

int main()
{
    Student pawel( 1, 5 ), pawelek( 1, 5 );
    if( pawel == pawelek )
         cout << pawel;
    else
         cout << "pawel != pawelek" << endl;
   
    return 0;
}
Kompiluje się i działa, wygląda na to że łapie. Tylko dalej nie wiem po co w przykładzie to drugie przeładowanie. Myślę, myślę i dochodzę do wniosku, że skoro w niej argumentem jest int, to ma umożliwić porównanie nr indeksu do zmiennej int. Jeśli tak, to przy użyciu tylko pierwszego przeładowania nie powinno się dać tego wykonać ( inaczej by nie miało sensu robienie oddzielnej funkcji porównującej indeks z int ). Sprawdzam więc:

C/C++
#include <iostream>
#include <string>

using namespace std;

class Student
{
    int nr_indeksu;
    float srednia_ocen;
public:
    Student( int nr = 0, float sr = 0 )
        : nr_indeksu( nr )
        , srednia_ocen( sr )
    {
    }
    friend ostream & operator <<( ostream & wyjscie, const Student & s )
    {
        return wyjscie << "Nr Indeksu: " << s.nr_indeksu << endl << "Średnia Ocen: " << s.srednia_ocen << endl;
    }
    int operator ==( const Student & q ) { return nr_indeksu == q.nr_indeksu; }
};

int main()
{
    Student pawel( 1, 5 );
    if( pawel == 1 )
         cout << pawel;
    else
         cout << "pawel != 1" << endl;
   
    return 0;
}

Ku mojemu zdziwieniu kod kompiluje a odpalony wyświetla indeks i średnią pawła. Czyli jednak drugie przeładowanie dla "==" albo ma inne zastosowanie, albo jest tu nie potrzebne. Myślę jednak, że autor nie podawałby przykładu zawierający zbędną funkcje. Więc głowię się nie mogąc zasnąć i nie mam pomysłu po co te:
int operator ==( const int & q ) { return nr_indeksu == q; }

Będę wdzięczny zarówno za odpowiedź na dręczące mnie pytanie, jak i za wytknięcie błędów w moim toku rozumowania, które umożliwią mi samodzielne rozwikłanie zagadki ( bardziej liczę na to drugie, po to tak się rozpisałem opisując główne przemyślenia ).
P-108029
alixir
» 2014-04-11 07:33:40
Myślę, myślę i dochodzę do wniosku, że skoro w niej argumentem jest int, to ma umożliwić porównanie nr indeksu do zmiennej int. Jeśli tak, to przy użyciu tylko pierwszego przeładowania nie powinno się dać tego wykonać ( inaczej by nie miało sensu robienie oddzielnej funkcji porównującej indeks z int )

Twoje rozumowanie jest słuszne. Przykład akurat ci zadziałał, bo jest dość prosty. W momencie gdy porównujesz
if( pawel == 1 )
 dla 1 wywolywany jest konstruktor klasy, którego pierwszym argumentm jest 1, a drugim 0. Podobne jest to do wywołania
Student nowy( 1, 0 )
 Wystarczy jednak zmienić kolejność argumentów konstruktora i zobaczysz różnicę w działaniu. Oto przykład (przetestuj i usuń komentarz drugiego przeciążenia):

C/C++
#include <iostream>
#include <string>

using namespace std;

class Student
{
    int nr_indeksu;
    float srednia_ocen;
public:
    Student( float sr = 0, int nr = 0 )
        : nr_indeksu( nr )
        , srednia_ocen( sr )
    {
    }
    friend ostream & operator <<( ostream & wyjscie, const Student & s )
    {
        return wyjscie << "Nr Indeksu: " << s.nr_indeksu << endl << "Srednia Ocen: " << s.srednia_ocen << endl;
    }
    int operator ==( const Student & q ) { return nr_indeksu == q.nr_indeksu; }
    //int operator ==( const int & q ) { return nr_indeksu == q; }
};

int main()
{
    Student pawel( 5, 1 );
    if( pawel == 1 )
         cout << pawel;
    else
         cout << "pawel != pawelek" << endl;
   
    return 0;
}
P-108031
« 1 »
  Strona 1 z 1