tworzenie implicit obiektu klasy

0

Hej

Dla tego przypadku:

#include <stdio.h>
#include <iostream>

class A {
  public:
     A(int x):y(x) 
     { 
         std::cout << y << std::endl;
     }
     
     bool operator==(const A& a)
     {
         return a.y == this->y;
     }
     
     bool operator>=(const A& a)
     {
         return this->y >= a.y;
     }
     
     int y;
};

int main()
{
    A(6) == A(6) >= A(5); //najpierw operacja >= bo ma wiekszy priorytet niz ==

    return 0;
}

output programu to 5,6,1,6
czyli niejawnie sie kontruktor stworzyl.
A dla tego błąd, trzeba operator porównywania deklarować i to poza klasą (w klasie nie pomaga):

#include <stdio.h>
#include <iostream>

class A {
  public:
     A(int x):y(x) 
     { 
         std::cout << y << std::endl;
     }
     
     bool operator==(const A& a)
     {
         return a.y == this->y;
     }
     
     bool operator>=(const A& a)
     {
         return this->y >= a.y;
     }
     
     int y;
};

/*bool operator==(bool x, const A& a)
{
    return (int)x == a.y;
}*/  //to musze odkomentowac by nie było błędu main.cpp:40:18: error: no match for ‘operator==’ (operand types are ‘bool’ and ‘A’)

int main()
{
    A(6) >= A(5) == A(6); //nie potrafi wywolac implicit kontruktora tutaj przed porównywaniem

    return 0;
}

Ktoś wie czemu tak jest że w jednym przypadku nie trzeba operatora porównywania a w drugim trzeba?

0

Operator == zdefiniowany wewnątrz klasy nie jest symetryczny. Aby zadziałał po lewej stronie zawsze musi być obiekt typu A.

// Pierwszy przypadek
(1) A(6) == A(6) >= A(5);
(2) A(6) == true ;
(3) A(6) == 1;  // niejawna konwersja do int
(4) A(6).operator==( 1 );  //  próba wywołania, funkcja nie przyjmuje wartości typu int, ale można użyć niejawnej konwersji z int to A. 
(5) A(6).operator==( A(1) ); // ostatecznie

// Drugi przypadek
(1) A(6) >= A(5) == A(6);
(2) true == A(6);  // błąd po lewej stronie typ bool , a po prawej typ obiektu nie może być zamieniony na bool

Dlatego w drugim przypadku wystarczy zamienić

A(6) >= A(5) == A(6);

na

A( A(6) >= A(5) ) == A(6);

IMHO bardziej czytelnym rozwiązaniem okazuje się tutaj zdefiniowanie operatora == na zewnątrz klasy.

Osobna kwestią jest poprawność powyższych przykładów od strony formalnej. Jaki jest sens porównania wartości typu bool z obiektem klasy A?

0

Jeśli przy porównaniu dwa operandy są różnego typu, następuje próba konwersji prawego operandu na typ lewego. Dlatego pierwszy przykład działa - bool daje się przekonwertować na A. Drugi przykład nie działa, bo A nie da się przekonwertować na bool. Dodaj operator konwersji na bool i zacznie działać.

1

Operatorów porównania nie można łączyć w takie ciągi i dlatego masz błąd.
Dlatego ta linijka: A(6) >= A(5) == A(6); jest bezsensu.
Na dodatek, nawet po poprawce, dalej jest bezsensu, bo z wynikiem trzeba coś zrobić.

Efektywnie ta linijka próbuje zrobić coś takiego:

{
    bool tmp = A(6) >= A(5);
    tmp  == A(6);
}

Radziłbym opanować najpierw podstawy składni C++ zanim się weźmiesz za przeładowywanie operatorów.

0

Dobra, nie doczytałem opisu problemu.

A cały problem rozchodzi się o to, że bool operator==(const A& b, const A& a) nie jest dokładnie tym samym co: bool A::operator==(const A& a) const.
Dowód: https://www.godbolt.org/z/vmEzGN

Nie chce mi się szukać wyjaśnienia w standardzie.
Generalnie chodzi o to, że operator zdefiniowany jako metoda klasy jest widoczny w zakresie klasy.
Jak pierwszym argumentem jest typ tej klasy, to operator staje się widoczny w wyrażeniu.
Jeśli pierwszym argumentem jest inny typ, to wtedy operator zdefiniowany jako metoda, nie bierze udziału w rozwiązywaniu przeładowywania operatorów, więc nie ma jak dość do domyślnej konwersji.

1 użytkowników online, w tym zalogowanych: 0, gości: 1