|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Registered User
Iscritto dal: May 2009
Messaggi: 300
|
[C++] Urgente: Magheggi con funzioni friend
Volevo sapere se si può e se no come si può fare qualcosa del genere:
Codice:
class A; class B { void funB(A a) {a.funA();} // VORREI CHE SIA CORRETTO (ORA E' SEGNALATO COME ERRORE PERCHE' funA NON E' DEFINITA) void funC(A a) {a.funA();} // DEVE ESSERE RILEVATO COME ERRORE } class A { friend void B::funB(A a); protected: void funA() {/*...*/}; } Ultima modifica di Ikon O'Cluster : 03-09-2009 alle 19:21. |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Direi che quello che vuoi fare non è fattibile e oltretutto pone di fronte ad errori di progettazione.
Perchè mai solo un metodo di B dovrebbe accedere ad A? Se spieghi meglio il contesto forse è possibile trovare una soluzione differente. funB e funC fanno parte dello stesso contesto ovvero class B, e se funC richiamasse funB più o meno direttamente dovrebbe segnalarti errore? Credo che la richiesta non sia ragionevole, anche perchè allora potresti pensare che funC richiami un metodo di class C dichiarata come friend di class B che a sua volta richiama funB, risultato atteso? |
![]() |
![]() |
![]() |
#3 |
Registered User
Iscritto dal: May 2009
Messaggi: 300
|
Perchè volevo che la classe B accedesse ad A soltanto con una funzione membro e non con tutte le funzioni membro. In realtà la mia situazione è questa.
Codice:
class A; class B { void funC(A a) {a.funB(a);} // PUO' ACCEDERE AD A SOLO SE CHIAMA funB protected: void funB(A a) {a.funA();} // VORREI CHE SIA CORRETTO (ORA E' SEGNALATO COME ERRORE PERCHE' funA NON E' DEFINITA) } class A { friend void B::funB(A a); protected: void funA() {/*...*/}; } Perchè funA è incaricata di modificare A. E funB è l'unica incaricata di accedere a B. Vorrei che funB-funA siano una specie di "ponte" tra A e B... Ultima modifica di Ikon O'Cluster : 04-09-2009 alle 10:05. |
![]() |
![]() |
![]() |
#4 |
Senior Member
Iscritto dal: Feb 2006
Messaggi: 1304
|
Secondo me, devi riorganizzare il codice e lasciar stare friend...
spesso quando c'è la stretta necessità di usare friend c'è un errore "di dominio": cioè, se B dipende così strettamente da alcune funzioni di A tanto da dover essere dichiarata friend, probabilmente quelle funzioni non stanno bene dove stanno. Potresti incapsularle in una classe C che le rende pubbliche, potresti spostarle in B, ecc. Magari se spieghi meglio il contesto possiamo aiutarti in questo... ![]() |
![]() |
![]() |
![]() |
#5 |
Registered User
Iscritto dal: May 2009
Messaggi: 300
|
Il codice sottomano non posso pubblicarlo perchè è secretato, ma il concetto è questo:
1) Esistono dei "semi-lavorati": Codice:
class SemiLavorato { protected: Tipo1 campo1; TipoN campoN; public: void set1(Tipo1 t) {campo1 = t;} void setN(TipoN t) {campoN = t;} Tipo1 get1() {return campo1;} TipoN getN() {returncampoN;} } Codice:
class Lavorazione { protected: Prodotto output; void lavorazione(Semilavorato sl) {output.tick(); output.trasformazione(sl);} public: void acquisisci(SemiLavorato sl) {qualcosa(); lavorazione(sl);} Prodotto estrai() {return p;} } Codice:
class Product { protected: unsigned int time1; unsigned int timeN; TipoFinito1 campo1; TipoFinitoN campoN; void tick() {time1++; timeN++;} // Deve poter essere eseguita solo da Lavorazione::lavorazione public: void trasformazione(SemiLavorato sl) {/* Lavora solo alcuni TipiFiniti ma non si sa quali a priori, quindi per quelli lavorati imposta timeX=0 per gli altri li lascia inalterati. */} } Quello che voglio è che solo Lavorazione possa effettuare lavorazioni su Prodotto. Una volta finita la lavorazione chi ottiene prodotto con estrai() non può più lavorarci sopra. Ma anche chi maneggia Lavorazione non deve poter arbitrariamente operare su Prodotto. In particolare non deve toccare i timeX e quindi invocare la tick(). Perlomeno deve poterci operare solo se effettua una acquisisci() o altre funzioni che richiamano trasformazione(). Ultima modifica di Ikon O'Cluster : 04-09-2009 alle 16:31. |
![]() |
![]() |
![]() |
#6 |
Senior Member
Iscritto dal: Feb 2006
Messaggi: 1304
|
Boh, mi sembra confuso
![]() Cmq una cosa che potresti fare molto semplice è mettere dentro a prodotto un bel bool "finalized" e un bel metodo void finalize(); così finalize è pubblico, ma quando viene chiamato "blocca" le modifiche a Prodotto. Altrimenti puoi sempre usare la convenzione _metodo() affiancata da un bel commento che invita a non usarlo sul metodo che vuoi rendere interno... ricorda che protected è pur sempre una convenzione, non è strettamente *necessario*. Nella quasi totalità delle librerie OOP è facile trovare metodi pubblici cosiddetti "internal" che servono proprio a questo scopo... |
![]() |
![]() |
![]() |
#7 | |||
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Quote:
A questo punto hai accesso a tutti i metodi protected. Dopotutto è un altro modo per rappresentare la composizione di oggetti, come l'avevi fatta te, solo che il legame diventa più stretto e sei sicuro che non si possa casta un ProductProcessing a Product Quote:
Quote:
Ultima modifica di tomminno : 04-09-2009 alle 19:06. |
|||
![]() |
![]() |
![]() |
#8 |
Registered User
Iscritto dal: May 2009
Messaggi: 300
|
Uhm... ci studio un po', cmq mi sembra pacifico il ragionamento di tommino. In ogni caso io ora ho definito friend l'intera classe e sostanzialmente è altrettanto pulito in termini di leggibilità/comprensione (anche dati i commenti).
Grazie per le risposte. |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 00:51.