|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#21 | |
|
Senior Member
Iscritto dal: Oct 2006
Città: Roma
Messaggi: 1383
|
Quote:
dovendo per forza palinfrascare agilmente io avrei preferito la definizione di Albi89 |
|
|
|
|
|
|
#22 | |
|
Senior Member
Iscritto dal: Oct 2006
Città: Roma
Messaggi: 1383
|
Quote:
*per sotto-oggetti intendo i campi di tipo classe. EDIT - anzi: se devo rappresentare in un programma una risorsa la cui creazione o acquisizione puó fallire, io preferisco sempre lanciare eccezioni dal costruttore, altrimenti il programma diventa piu complesso perché per quella classe devo prevedere due possibili stati: "creato ma non inizializzato" e "creato e inizializzato". i controlli "assert" a quel punto fioriscono. EDIT2 - anzi, tre stati: "creato ma non inizializzato", "creato e inizializzato con successo" e "creato ma inizializzazione fallita".
__________________
3D Volley Demo (Facebook) | Reversi (Facebook) | Blockout (Facebook) | Puzzle15 (Facebook) Ultima modifica di fero86 : 07-08-2010 alle 20:22. |
|
|
|
|
|
|
#23 |
|
Senior Member
Iscritto dal: Oct 2006
Città: Roma
Messaggi: 1383
|
qualche ulteriore dettaglio?
|
|
|
|
|
|
#24 |
|
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Devi gestire contemporaneamente due eccezione e il programma qualsiasi scelga perde informazioni.
Esempio: Codice:
#include <iostream>
struct Bar{};
struct Foo
{
~Foo(){ throw Bar(); }
};
void g()
{
throw 42;
}
void f()
{
try
{
Foo f;
g();
}
catch( int )
{
std::cout << "Got int" << std::endl;
}
}
int main()
{
try
{
f();
}
catch( const Bar& b )
{
std::cout << "Got Bar" << std::endl;
}
}
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
|
|
|
|
|
#25 |
|
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Nel mio contesto, un altro oggetto che ha la responsabilita' di deallocare l'istanza in questione, ne piu' ne meno.
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
|
|
|
|
|
#26 | ||
|
Senior Member
Iscritto dal: Oct 2006
Città: Roma
Messaggi: 1383
|
vero, sono d'accordo che lanciare eccezioni dai distruttori sia del tutto da evitare visto che i distruttori vengono invocati anche in caso di stack unwinding provocato da un'eccezione, infatti chiedevo chiarimenti perché avevo letto male questo post:
Quote:
Quote:
parlando a livello intuitivo non é detto che il "proprietario" di un oggetto sia un altro oggetto. il concetto di livello di astrazione mi piaceva di piu
|
||
|
|
|
|
|
#27 | |
|
Bannato
Iscritto dal: Oct 2002
Città: Vicino Fermo Mercatino:più di 100 trattative tutte OK
Messaggi: 4651
|
Quote:
il chiamante quando sa che non gli serve più. Chi dealloca il puntatore? Scusa, ma come si dealloca un puntatore? al massimo lo metti =0. esempio pratico: factory che crea una instanza di un oggetto di tipo di un interfaccia generico. Voglio vedere come fai a far distruggere l'oggetto in questo caso alla classe stessa -.-". Ultima modifica di Wing_Zero : 08-08-2010 alle 10:22. |
|
|
|
|
|
|
#28 | ||
|
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Quote:
Chi ti dice che il chiamato non utilizzi quello stesso oggetto per i fatti suoi? Che non abbia passato quello stesso oggetto ad altri chiamanti? Uno dei principi base della programmazione ad oggetti è l'incapsulamento, io chiamante non devo conoscere il funzionamento interno del chiamato. Secondo il tuo ragionamento invece il chiamante deve conoscere il comportamento interno del chiamato. In caso di modifiche interne a quest'ultimo, sei obbligato a rivedere anche il primo. Quote:
Chi ti dice che il Factory non sia di tipo "singleton" ovvero che ritorna sempre la stessa istanza a parità di parametri in ingresso? Se il tuo chiamante ne facesse la delete ti ritroveresti sicuramente nei guai. |
||
|
|
|
|
|
#29 | ||
|
Senior Member
Iscritto dal: Sep 2005
Messaggi: 2717
|
scusandomi per l'intromissione ...
Quote:
per esempio, quando ritorni un tipo per valore non è forse la dichiarazione stessa del metodo che ti dice che ogni volta avrai una nuova istanza ? allo stesso modo, in una situazione in cui può avere senso, come appunto factory in cui per il tipo prodotto è usata a modo di interfaccia una classe astratta, parte della definizione(semantica) formale come api di un metodo può benissimo essere che ti restituisce un puntatore ad una nuova istanza o invece sempre alla stessa, e la cosa essere tranquillamente parte della documentazione di progetto; da qui ce ne passa dal dire che il chiamante sia fortemente dipendente dall'implementazione del chiamato. andiamo, ci sono api anche molto blasonate con le quali c'è una lista di cose che devi sapere (e quando la documentaziome delle medesime include la lista completa già va di lusso ) quando passi loro un puntatore o te ne ritornano uno, per evitare potenziali "effetti collaterali" ...non voglio sostenere che non sia opportuno o sia indifferente distruggere un oggetto sullo heap con uno statement parte della stessa classe che lo ha creato, per carità, ma non sempre è possibile applicare tale "regola" tantomeno mi voglio addentrare su cosa sia più "elegante" o meno etc, ma francamente più passa il tempo meno mi convince che per ogni cosa esista la regoletta universale che va sempre bene e che se "sgarri" allora devi buttare via tutto Quote:
può sicuramente essere un'ottima idea, ma personalmente lo vedo più come un miglioramento di dettaglio rispetto ai concetti discussi: già solo il fatto che la factory ti ritorni (per valore ovviamente) un oggetto auto_ptr ti dice che creerà una nuova istanza ogni volta, un miglioramento perché è la definizione stessa del metodo che ti esclude l'opzione singleton rispetto al ritornare un puntatore, ma non è certo un ipotetico livello di astrazione in più che ti permette id avere indifferentemente la factory normale oppure singleton senza modificare né la definizioen del metodo né il chiamante; poi cmq l'oggetto sullo heap verrebbe distrutto quando l'oggetto di tipo auto_ptr va fuori scope, quindi nel chiamante e cmq non nel codice classe che lo ha creato, la nostra "regola aurea" potrebbe in fondo ancora lagnarsene formalmente, metti che per caso la situazione lato factory fosse molto complessa ed il codice che crea effettivamente l'istanza non sa che poi verrà passata esternamente trmite un wrapper del puntatore che "takes ownership" dell'istanza ...se ci vogliamo arrovellare concettualmente non cambuia molto rispetto alla questione iniziale inoltre, tanto per rimanere in tema di factory e "regole assolute" e signleton o meno, trovi pure tanti che predicano animatamente contro il singleton pattern, qundi in questo esempio ci sarebbe pure un'ulteriore "regola assoluta" che andrebbe a risolvere la diatriba "a monte" anche se il metodo in questione ritornasse solo un normale puntatore ps: se il l'applicazione del concetto di definizione di un tipo come interfaccia ed il pattern della factory sono in voga ormai da molti anni, consolidati e che io sappia tuttora molto usati e con "reputazione" positiva, ed allo stesso tempo il c++ non implementa esplicitamente il concetto di interfaccia, in fondo non è certo colpa degli utilizzatori del c++ pps: una precisazione, devo scappare di fretta e non ho tempo di correggere bene la forma del post, temo di aver unsato una o più volte la parola "definizione" al posto di "dichiarazione" relativamente ad un metodo (spesso "definizione" è usato come sinonimo di implementazione del metodo)
__________________
"La teoria è quando si sa tutto ma non funziona niente. La pratica è quando funziona tutto ma non si sa il perché. In ogni caso si finisce sempre con il coniugare la teoria con la pratica: non funziona niente e non si sa il perché." - Albert Einstein fonte: http://it.wikiquote.org/wiki/Albert_Einstein Ultima modifica di MenageZero : 08-08-2010 alle 13:13. |
||
|
|
|
|
|
#30 | |||||||||
|
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Quote:
Quote:
Ma certamente non esiste una sola API che ti ritorna un riferimento e nella documentazione ti dice che quell'oggetto te lo devi deallocare. Quote:
Se non viene fatto il più delle volte è perchè trovi una strutturazione molto alla C. Quote:
Per questo si parla di best practices. Quote:
Quote:
Quote:
E' vero che tanti dicono male del singleton, ma in un programma ci sono delle variabili effettivamente globali, tipo le configurazioni. Oppure pensa solo all'MVC se dei controller devono condividere lo stesso Model a chi chiederanno l'istanza del Model? Se non lo fai con un factory "singleton" io non ho molte altre alternative, se non quella che gli venga passato dal chiamante, ma non necessariamente il chiamante è in un contesto tale da avere un riferimento al Model richiesto. Qualcuno ha altre alternative? Quote:
Sennò perchè non consigliare di scrivere tutto nel main così ci si evitano direttamente chiamate a funzioni o metodi con tutti gli eventuali problemi della gestione del ritorno? Quote:
|
|||||||||
|
|
|
|
|
#31 | ||
|
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Quote:
Quote:
Una alternativa e' forzare l'uso di una factory, con costruttori privati e friend factory. In quel modo puoi inizializzare come vuoi ed evitare qualsiasi stato invalido (ed avere dei costruttori "virtuali")
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
||
|
|
|
|
|
#32 |
|
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
L'oggetto da qualche parte deve stare, che sia lo stack delle chiamate, una variabile globale o un qualsiasi struttura dati. Se il puntatore all'oggetto e' presente in piu' parti bisogna decidere dove/da chi deve venire deallocato (o ricorrere a oggetti tipo shared_ptr), Il senso del mio intervento era questo, niente di piu'.
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
|
|
|
|
|
#33 | |||||||||
|
Senior Member
Iscritto dal: Sep 2005
Messaggi: 2717
|
Quote:
situazione ed automatizzare la distruzione usando qualcosa come auto_ptr o shared_ptr, come hai giustamente ricordato e mi pare di aver convenuto con te sull'opportunità di farlo; rimane il fatto che l'oggetto sullo heap non verrà distrutto dalla classe che lo ha creato e mi pare che proprio questo sembrava dover essere "scandaloso" a prescindere da tutto. l'alternativa è usare come interfaccia una classe non astratta (i metodi della quale ovviamente sarebbero implementati per non fare nulla, trattandosi dela "paradosso" di una istanza di un'interfaccia, nel caso venisse creato un oggetto di tale tipo) e ritornare l'oggeto del tipo concreto prodotto per valore, ma cadrebbe lo spunto iniziale visto che l'oggetto di interesse non sarebbe più sullo heap. (la discussione concettuale si sposterebbe altrove, immagino sia molto criticabile anche il fatto di poter creare un'istanza di un'interfaccia, anche se sarebbe inutile e non verrebbe mai effettivamente fatto) Quote:
per es questo metodo ritorna un puntatore ad un oggetto e la documentazione non ti dice nulla sul fatto se diventa roba tua, l'oggetto, o se sarà la lib. a gestirne il ciclo di vita ... poi, visto che si può supporre che by design avranno teso a minimizzare le probabilità di leak, e visto che non dicono esplcitamente di distruggerlo finito l'uso, si può optare per evitare la delete nel chiamante, ma in prima istanza rimane solo una ipotesi/deduzione, .. .una riga in più nella documentazione non faceva male ... ... tanto più che, senza nemmeno farlo apposta trovo nella documentazione della medesima classe uno snippet di esempio in cui al contrario un ulteriore oggetto restituito per indirizzo viene proprio deallocato dal chiamante quando non gli serve più ![]() inoltre ben più comune è il caso "inverso" ma concettualmente simile, in cui passi un puntatore ad una api, puntatore ad un oggetto che hai creato nel chiamante o cmq altrove nel tuo codice "client" rispetto alla lib, ma che non avrai necessità o anche non dovrai permetterti di deallocare. situazione opposta alla factory ma che ripropone ancora un caso di oggetti sullo heap non distrutti dalla classe che li ha creati. Quote:
Quote:
... cmq nessuna "animosità" , per carità Quote:
Quote:
Quote:
Quote:
Quote:
__________________
"La teoria è quando si sa tutto ma non funziona niente. La pratica è quando funziona tutto ma non si sa il perché. In ogni caso si finisce sempre con il coniugare la teoria con la pratica: non funziona niente e non si sa il perché." - Albert Einstein fonte: http://it.wikiquote.org/wiki/Albert_Einstein Ultima modifica di MenageZero : 08-08-2010 alle 21:50. |
|||||||||
|
|
|
|
|
#34 | |
|
Bannato
Iscritto dal: Oct 2002
Città: Vicino Fermo Mercatino:più di 100 trattative tutte OK
Messaggi: 4651
|
Quote:
Penso sia troppo palese per non concordare su questo punto. |
|
|
|
|
|
|
#35 | ||
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
Quote:
Comunque riprendendo l'esempio che hai fatto: Codice:
Object &Classe::object()
{
Object* object = new object();
return object;
}
O Object * come tipo di ritorno ? Sui Factory object o Factory method... Tipicamente mi piace che non ritornino per riferimento o per puntatore. Dal punto di vista prestazionale certo non è la scelta migliore ed in altri casi non è nemmeno la scelta migliore dal punto di vista architetturale. Nel caso in cui si ritorni un puntatore, allora è implicito per la natura dei pattern stessi che perdano il controllo su ciò che producono. Solitamente se si ritorna per riferimento, il chiamante ha in mano un alias ad un altro oggetto, quindi implicitamente si accetta che l'oggetto abbia vita oltre alla distruzione dell'alias. Mi sembra francamente la soluzione peggiore per uno dei pattern sopra, a meno che il Factory object (farlo con un Factory method sarebbe assurdo) non resti il proprietario dell'oggetto e ne sia responsabile anche della deallocazione. Giusto per fare un esempio, generalizzando: - se ritorno un puntatore ad una macchina è come se mi dicessero: "la macchina è tua e ti regalo anche le chiavi" - se invece ritorno un riferimento ad una macchina è come se mi dicessero: "ti presto la macchina, ma resta mia, usala con le chiavi di riserva, ma le altre ce l'ho io, quindi la posso usare anche io" Ultima modifica di cionci : 09-08-2010 alle 11:13. |
||
|
|
|
|
|
#36 | |
|
Senior Member
Iscritto dal: Sep 2005
Messaggi: 2717
|
Quote:
secondo me l' "&" è una svista, azzarderi che intendesse Qbject* come tipo di ritorno visto che si parlava di lasciare al chiamante la distruzione di object in uno scenario del genere penso si posa considerare l'assunzione che chi ritorna Object* perda ogni riferimento e controllo su object, visto che appunto il chiamato sarebbe una classe Factory; come tra l'altro tu stesso puntualizzi nel discutere l'opzione con Object* come tipo di ritorno, no ? forse sbaglio ma una factory che rimane proprietario delle istanze prodotto mi parrebbe ben poco factory semanticamente un chiamato che ritorna un puntatore o riferimento ed è proprietario dell'oggetto(o che cmq semanticamente include l'assunzione che il chiamante non deve deallocare l'oggetto) mi da più l'dea di situazione da pattern tipo registry/repository o semplicemente "mappa", in generale ... cmq non factory .. che ne pensi ? edit: volevo anche chiedere un parere (anche a chiunque altro volesse dire al sua ovviamente)su una cosa che avevo accennato in un altro post, ovvero usare come interfaccia una classe concreta (con implementazione dei relativi metodi che ovviamente non fa nulla, e che magari ha un metodo - per es un cosa come bool isNull() - per distinguere se un oggeto di quel tipo è veramente una implementazione dell'interfaccia o una inutile istanza dell' "interfaccia" stessa, anche se in tale scenario probabilmente poco ortdosso ovviamente l'assunzione sarebbe che nessuno creerebbe mai un'istanza dell' "interfaccia") tale approccio potrebbe servire , in una implementazione di factory, per poter ritornare le istanze prodotto effettivamente per valore aggirando totalmente la questione di dover avere un oggetto sullo heap che non potrà essere distrutto dalla stessa classe/livello di astrazione che lo ha creato. ovviamente il tutto sposterebbe i problemi concettuali sul fatto di ritrovarsi un' "intefaccia" istanziabile, anche se non ci sarebbe motivo di crearne istanze dirette. magari è riternuto molto peggio che il factory method ritornante un puntatore (magari wrappato con auto_ptr o altro) "comprensivo" di ownership sull'oggetto puntato
__________________
"La teoria è quando si sa tutto ma non funziona niente. La pratica è quando funziona tutto ma non si sa il perché. In ogni caso si finisce sempre con il coniugare la teoria con la pratica: non funziona niente e non si sa il perché." - Albert Einstein fonte: http://it.wikiquote.org/wiki/Albert_Einstein Ultima modifica di MenageZero : 09-08-2010 alle 14:06. |
|
|
|
|
|
|
#37 | |||
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Quote:
Codice:
Object &Classe::object()
{
Object* object = new object();
return *object;
}
Quote:
Per la parte creazionale resta comunque un factory, perché è l'unico che può creare un oggetto di un certo tipo. Quote:
|
|||
|
|
|
|
|
#38 | |
|
Bannato
Iscritto dal: Oct 2002
Città: Vicino Fermo Mercatino:più di 100 trattative tutte OK
Messaggi: 4651
|
Quote:
Come ha appunto fatto notare managezero in un caso del genere la factory ( prendendo l'esempio della macchina) "ti regala l'unica copia di chiavi che esiste". In questo caso risulta palese che l'oggetto debba essere distrutto fuori dalla classe stessa... |
|
|
|
|
|
|
#39 |
|
Senior Member
Iscritto dal: Sep 2005
Messaggi: 2717
|
in effetti magari l'idea l'avevo presa da qualche parte, non ho esattamente una memoria di ferro con i nomi, specie se sono di qualcosa che non applico spesso o recentemente
da quello che vedo con una velocissima (qundi imprecisissima) google-ata probabilmente una classe fatta in quel modo può esserevi assimilata, solo a prima vista non ho notato riferimenti a farne un uso da interfaccia
__________________
"La teoria è quando si sa tutto ma non funziona niente. La pratica è quando funziona tutto ma non si sa il perché. In ogni caso si finisce sempre con il coniugare la teoria con la pratica: non funziona niente e non si sa il perché." - Albert Einstein fonte: http://it.wikiquote.org/wiki/Albert_Einstein Ultima modifica di MenageZero : 09-08-2010 alle 20:31. |
|
|
|
|
|
#40 | |
|
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Il Null Pattern comunque può essere usato anche con l'interfaccia, si estrae l'interfaccia (classe astratta) dal Null Pattern che coinciderà con quella delle implementazione concrete.
Quindi il Null Pattern deriverà dalla classe base astratta così come le altre implementazioni. Quote:
Resta il fatto che se per una factory la cosa è palese, non è sempre palese in altri casi. In questo caso non trovo necessario dover ritornare un puntatore. Meglio un riferimento ma non allocato dinamicamente. Ultima modifica di cionci : 10-08-2010 alle 01:11. |
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 18:49.












) quando passi loro un puntatore o te ne ritornano uno, per evitare potenziali "effetti collaterali" ...
... cmq nessuna "animosità" , per carità








