[C++] Funzioni e classi Friend

starsuper
Salve a tutti, c'è una cosa che non capisco. Sto studiando il c++ e l'attributo FRIEND ma a quanto ho capito, permette a funzioni esterne di accedere anche a membri protected e private della classe in cui la funzione è dichiarata. Riporto da cppreference:

// friend functions
#include <iostream>
using namespace std;

class Rectangle {
    int width, height;
  public:
    Rectangle() {}
    Rectangle (int x, int y) : width(x), height(y) {}
    int area() {return width * height;}
    friend Rectangle duplicate (const Rectangle&);
};

Rectangle duplicate (const Rectangle& param)
{
  Rectangle res;
  res.width = param.width*2;
  res.height = param.height*2;
  return res;
}

int main () {
  Rectangle foo;
  Rectangle bar (2,3);
  foo = duplicate (bar);
  cout << foo.area() << '\n';
  return 0;
}


Qui si dice che poichè Duplicate non è dichiarata all'interno della classe essa è da considerarsi esterna.
Ma io so che in teoria nella classe andrebbero dichiarati solo i prototipi e le funzioni andrebbero o nello stile file del main o in un .cpp a parte. Allora mi viene detto che solamente le funzioni dichiarate dentro alla classe (magari in maniera inline) sono da considerarsi funzioni membro?

Capite che voglio dire? Cioè secondo me anche senza friend la funzione duplicate avrebbe potuto accedere ai membri in quanto sarebbe stato presente il suo prototipo all'interno della classe.

Sbaglio? Inoltre, essendo dichiarata public la possono richiamare anche dal main, quindi perche usare friend?


Grazie!

Risposte
Raptorista1
Il fatto che sia dichiarata friend indica che non è una funzione membro, e infatti nel codice di esempio non viene utilizzata come bar.duplicate() ma come duplicate(bar).
Ho risposto alla domanda?

starsuper
Si hai capito ed ho capito anche io nel frattempo :lol:

Quindi se io commentassi la riga che inizia con l'attributo friend, duplicate sarebbe una qualsiasi funzione esterna che non puo accedere ai membri della classe perchè essi sono private giusto?
Aggiungendo il prototipo con friend permetto invece di ammettere duplicate come amica.

Ma in definitva Friend si usa in queste circostanze, quando una funzione non membro o insomma non interna alla classe vuole accedere ai dati che sono all'interno di una classe?

Raptorista1
"starsuper":

Quindi se io commentassi la riga che inizia con l'attributo friend, duplicate sarebbe una qualsiasi funzione esterna che non puo accedere ai membri della classe perchè essi sono private giusto?

Questo puoi provarlo tu stesso.

"starsuper":

Ma in definitva Friend si usa in queste circostanze, quando una funzione non membro o insomma non interna alla classe vuole accedere ai dati che sono all'interno di una classe?

Sì. L'utilizzo di friend è comunque da riservarsi per pochi casi particolari.

apatriarca
Si tratta di una di quelle funzionalità di dubbia utilità il cui uso è normalmente indice di cattiva progettazione. Tuttavia l'uso mostrato non è quello più comune. La parola chiave friend è infatti principalmente usata per permettere ad una classe di accedere alla parte privata di un'altra classe. Nel tuo esempio non è infatti chiaro perché la funzione sia stata creata come funzione friend e non come funzione membro (o perché si sia deciso di non fornire informazioni riguardo a larghezza e altezza in modo pubblico). Oltretutto la funzionalità della funzione è quella del costruttore di copia o dell'operatore di assegnamento. Quando ad essere friend è una classe ha invece normalmente un po' più senso (ma spesso ci sono alternative migliori).

starsuper
"apatriarca":
Si tratta di una di quelle funzionalità di dubbia utilità il cui uso è normalmente indice di cattiva progettazione. Tuttavia l'uso mostrato non è quello più comune. La parola chiave friend è infatti principalmente usata per permettere ad una classe di accedere alla parte privata di un'altra classe. Nel tuo esempio non è infatti chiaro perché la funzione sia stata creata come funzione friend e non come funzione membro (o perché si sia deciso di non fornire informazioni riguardo a larghezza e altezza in modo pubblico). Oltretutto la funzionalità della funzione è quella del costruttore di copia o dell'operatore di assegnamento. Quando ad essere friend è una classe ha invece normalmente un po' più senso (ma spesso ci sono alternative migliori).


Si in effetti tramite altri esempi ho capito meglio. Diciamo che puo essere utile quando viene aggiunta una funzione postuma al codice e non si vuole andare a rimettere mano a tutte le variabili precedentemente dichiarate nella classe, le quali , potrebbero causare problemi se modificate in visibilità...

apatriarca
Aumentare la visibilità non è un problema e non lo è neanche la creazione di nuove funzioni membro per accedere a tali informazioni private. È più che altro utili in situazioni in cui per motivi di coerenza sia necessario usare funzioni non membro. Per esempio per la serializzazione. In questi casi è meglio friend, ma sono casi molto particolari.

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.