funkcje zaprzyjaźnione i symbole *, &

0

Czytam o funkcjach zaprzyjaźnionych i o ile idea wydaje sie być prosta, o tyle nie rozumiem żadnego z przykładów.

Pierwszy:

class Accumulator
{
private:
    int m_nValue;
public:
    Accumulator() { m_nValue = 0; }
    void Add(int nValue) { m_nValue += nValue; }
 
    // Make the Reset() function a friend of this class
    friend void Reset(Accumulator &cAccumulator);
};
 
// Reset() is now a friend of the Accumulator class
void Reset(Accumulator &cAccumulator)
{
    // And can access the private data of Accumulator objects
    cAccumulator.m_nValue = 0;
}
 

Drugi (fragment):

class Zakres {
       
           int lewy, prawy;
           friend void isInside(const Punkt*, const Zakres*);
       
           public:
           Zakres(int lewy = 0, int prawy = 0)
               : lewy(lewy), prawy(prawy)
           { }
            }; 

Trzeci:

 class K {
   friend void fun( K& ); // deklaracja przyjaźni
   friend void Y::fun( K& ); // deklaracja przyjaźni funkcji składowej klasy 'Y'
   private:
     int x;
 };
 
 void fun( K& obiekt ) {
   obiekt.x = 12; // nie byłoby możliwe to przypisanie bez określenia przyjaźni
 } 

Nie rozumiem dlaczego w pierwszym piszemy ze znakiem & np. &cAccumulator, w drugim jest Punkt*, a w trzecim jeszcze inaczej bo K&. Co oznaczają te zapisy? Proszę o pomoc.

1

Czasami lepiej użyć wskaźnika (*) a czasami referencji (&).

0

To o co pytasz to nie jest nic związanego z zaprzyjaźnianiem klas a są to po prostu podstawy języka.

&// referencja
*// wskaźnik

Poczytaj o nich a wszystko będzie jasne. W Internecie dużo materiałów na ten temat, więc nie ma sensu się rozpisywać.

Jeśli w danej funkcji, metodzie nie musisz operować na pamięci(alokowanie, zwalnianie) zmiennej przekazywanej to lepsza referencja. Jeśli jednak trzeba coś alokować dynamicznie to wtedy wskaźniki są przydatne.

0

Dziękuję. A jaka jest zasadnicza różnica pomiędzy &a i a&?
I rozumiem, że tam nie może być inaczej (tylko referencja lub wskaźnik) ponieważ funkcje zaprzyjaźnione mają mieć dostęp do istniejących już składowych w klasie i tylko niejako więc pobierać sobie te wartości spod danego adresu?

1

To co podajesz jako przykład to źle czytasz. Otóż poniższy zapis oznacza to samo.

Typ& zmienna; // referencja na Typ
Typ &zmienna2; // tak samo jak wyżej

// deklaracje nie potrzebują nazywania zmiennych a więc możliwy jest zapis
void metoda( Typ& );

// definicja natomiast potrzebuje
void metoda( Typ& _zmienna )
{
// operacje na _zmienna
}
0

a czemu w tym fragmencie:

 
class Zakres {
 
           int lewy, prawy;
           friend void isInside(const Punkt*, const Zakres*);
 
           public:
           Zakres(int lewy = 0, int prawy = 0)
               : lewy(lewy), prawy(prawy)
           { }
            }; 

we wskaźnikach, nie ma też podobnej notacji co w referencjach jak: *typ nazwa. Chyba dla utrudnienia jest na odwrót ... :/ mam nadzieje szybko zakończyć egzamin i przygode z tym jezykiem :/

1

Przy deklaracjach nazwę można pominąć, przy definicji musi już być taka notacja.

0

a jak napiszę tak:
friend void isInside(const *Punkt, const *Zakres);
to zadziała?

1

Dziękuję. A jaka jest zasadnicza różnica pomiędzy &a i a&?

Kolejność jest taka:

typ & zmienna

poniższe zapisy są równoważne:

typ& zmienna
typ &zmienna

stąd jeśli widzisz &a to a jest nazwą zmiennej,
a jeśli widzisz a& to a jest nazwą typu.

0

a jak będzie co do mojego poprzedniego pytania?

1
robalos napisał(a):

I rozumiem, że tam nie może być inaczej (tylko referencja lub wskaźnik) ponieważ funkcje zaprzyjaźnione mają mieć dostęp do istniejących już składowych w klasie i tylko niejako więc pobierać sobie te wartości spod danego adresu?

Nie. Funkcja zaprzyjaźniona może przyjmować obiekt przez wartość (nic przez to nie traci względem zakresu widoczności klasy).

0

To jeszcze na koniec można prosić o jakiś przykład z tym przekazaniem obiektu? Może lepiej mi to będzie zrozumieć.

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