Tenere traccia di oggetti cancellati runtime

di il
7 risposte

Tenere traccia di oggetti cancellati runtime

Salve a tutti.
Ho una classe che crea "Oggetti", ognuno con dei suoi dati e in particolare un numero "Identificativo".
L'utente dall'interfaccia può crearne ed eliminarne liberamente, questi vengono sistemati in una lista "ListaOggettiPossibili".
Questi rappresentano dei tipi di oggetti possibili, gli oggetti vengono poi inseriti in una seconda lista "Mappa".
Da quando si trovano in questa lista, sono fuori dal controllo dell'utente, si replicano e si cancellano autonomamente mantenendo però il numero Identificativo (che è stato copiato dalla lista).

L'utente deve essere informato di quanti oggetti della Mappa vengono cancellati.
Quindi ogni volta che bisogna cancellare un oggetto da Mappa uso un ciclo e confronto l'Identificativo dell'oggetto in Mappa con tutti quelli della ListaOggettiPossibili.

Ecco un esempio:

#include <vector>
#include <array>


class StatisticheOggetti
{
public:
        static std::vector<StatisticheOggetti> ListaStatistiche;
	int Cancellati;
	int Spostati;
};

class Oggetti
{
public:
	int Identificatore;
	int Dati;

	static std::vector<Oggetti> ListaOggettiPossibili;
	
	
};



class OggettiReali
{
public:
	static std::vector<Oggetti> Mappa;
	static void Aggiungi(Oggetti ogg) 
	{
		Mappa.push_back(ogg);
	}
	static void Cancella(int indice)
	{
		for (int i = 0; i < Oggetti::ListaOggettiPossibili.size(); i++)
			if (Oggetti::ListaOggettiPossibili[i].Identificatore == Mappa[indice].Identificatore)
			{
				Oggetti::ListaStatistiche[i].Cancellati++;
				Mappa.erase(Mappa.begin() + indice);
				break;
			}
	}
};
Vengo al dunque.
Deve esistere sicuramente un modo migliore di ottenere quello che voglio, vorrei eliminare il ciclo di controllo per trovare l'"oggetto tipo" da cui è stato copiato l'oggettoMappa.
Ad esempio:

Se potessi rappresentare ogni oggetto della lista come una classe a sé, potrei dichiarare i "Cancellati" come membro static dell'Oggetto, questo sarebbe perfetto, ma è possibile dal momento che la lista è variabile?

Si potrebbe pensare di usare l'Identificativo per individuare l'analogo della lista tramite indice, ma no! ..Perchè la lista può cambiare e quindi l'Identificato NON coincide con l'indice dell'oggetto in lista.

Grazie infinite.

7 Risposte

  • Re: Tenere traccia di oggetti cancellati runtime

    Non ho chiaro se un identificativo corrisponde un singolo oggetto o una famiglia di oggetti.
  • Re: Tenere traccia di oggetti cancellati runtime

    Una famiglia di oggetti, lo uso per "ritrovare" da quale oggetto è stato copiato.. ma vorrei evitare.
  • Re: Tenere traccia di oggetti cancellati runtime

    Si, esiste un modo decisamente migliore!

    Devi usare il design pattern (https://sourcemaking.com/design_pattern) OBSERVER/OBSERVED.

    Fondamentalmente: la tua Mappa non e' una semplice mappa, ma un oggetto che contiene una mappa, che si comporta come una mappa, ma che ogni volta che succede qualcosa alla mappa interna, viene generato un EVENTO (aggiunto un elemento alla mappa, rimosso un elemento dalla mappa, ..)

    Ora, chiunque sia interessato a sapere che cosa succede nella mappa, si REGISTRA come LISTENER per uno o piu' eventi che il tuo superoggetto Mappa puo' generare.

    Ed il gioco e' fatto.

    A descriverlo e' complicato, ad implementarlo, banale.

    Ma, ovviamente, serve avere chiaro i concetti coinvolti


    Piu' in generale, la definizione di oggetto, nella programmazione ad oggetti, e' sempre stata fatta in modo parziale:

    un oggetto ha uno stato (i membri di istanza) ed una serie di operazioni disponibili (i metodi)

    I problema dei metodi e che questi vengono usati da qualcun altro (lasciamo stare il fatto che l'oggetto puo' usare i suoi stessi metodi).
    Messa cosi', se non c'e' nessuno che interagisce con l'oggetto, questo rimane assolutamente silente (e non serve a niente).

    Manca la parte: l'oggetto emette, di sua iniziativa, degli EVENTI.

    Questo fa si che l'oggetto possa fare qualcosa anche senza che nessuno gli rompa le scatole.
    Pero' chi vuole, puo' REGISTRARSI per sapere che cosa l'oggetto sta' combinando.
  • Re: Tenere traccia di oggetti cancellati runtime


    Grazie, esattamente quello che cercavo!
  • Re: Tenere traccia di oggetti cancellati runtime

    Temo di non aver risolto il problema di fondo!
    Faccio riferimento in particolare all'esempio esplicativo riportato qui


    Il mio problema è che mia lista di Observer a volte cambia indirizzo in memoria, perchè l'utente può rimuovere gli Observer dalla lista ( un std::vector).
    Il Subject punta all'indirizzo di memoria del suo Observer, ma quando il vector di Observer verrà riordinato per un .erase() il Subject continuerà a puntare a quell'indirizzo, dove si troverà l'Observer sbagliato o altre parti del programma.

    Sbaglio o dico giusto?
  • Re: Tenere traccia di oggetti cancellati runtime

    Evidentemente stai osservando l'oggetto sbagliato!

    E' ovvio che l'oggetto osservato da un osservatore, NON DEVE scoparire misteriosamente, o morire di morte prematura

    Rivediamo:

    l'osservatore osserva la COLLEZIONE che contiene gli oggetti da osservare.

    ci sono piu' osservatori, interessati a insiemi diversi di oggetti osservabili (che gli insiemi siano a intersezione vuota oppure no, non e' un problema, al momento)

    Ogni oggetto osservabile contenuto nella collezione deve avere un ID.

    L'osservatore riceve le notifiche a fronte di nascita e morte di OGNI oggetto osservabile, MA si interessa SOLO a quelli che hanno un ID che soddisfa qualche regola.

    Tra l'altro, da quanto capisco dal tuo primo post, in qualche modo queste informazioni le hai gia'
  • Re: Tenere traccia di oggetti cancellati runtime

    In effetti, credo mi sfugga qualcosa, ho fatto una sintesi di quello che ho capito dai vari esempi.
    Nell'esempio semplificato che riporto esegue l'operazione senza errori, ma non aumenta la variabile dell'osservatore che tiene il conto degli eventi/stati (cntTot).

    Non ho usato un numero identificativo perchè negli esempi trovati non mi è sembrato lo utilizzassero..
    Inoltre non ho una Lista di osservatori come negli esempi perchè nel mio caso vari soggetti sono seguiti da un unico osservatore.
    Per il resto mi pare sia identico..
    class Animale;  //soggetto già conosciuto
    
    class AniModel{  //osservatore
    
    	int cntTot;
    	
    	static std::vector<AniModel> ListaStats; //lista di osservatori
    
    public:
    	
    	AniModel():cntTot(0) {}
    	~AniModel() {}
    
    	void AggStatVivi(Animale &an) {++cntTot;}   //chiamata di aggiornamento
    
    };
    
    
    class Animale  //soggetto
    {
    	
    	AniModel *model;
    	
    	int EtaAttuale;
    	bool Fem;
    
    public:
    	
    	class AniModel *GetModel() {return model;}     //puntatore  a modello
    	
    	Animale(int eta, bool fem, AniModel &mod):EtaAttuale(eta), Fem(fem), model(&mod) {} //punta al modello che viene fornito nell'init
    	
    
    
    };
    
    
    class Casella
    {
    	static const int GrMp = 60;
    	std::vector<Animale> AnimaliVivi;   
    	static std::array<std::array<Casella, GrMp>, GrMp> Mappa;  //array 2D di Casella, ogni casella contiene una lista di soggetti
    public:
    	
    	Casella() {}
    	~Casella() {}
    
    	
    	static void OperAni(const int x, const int y) {                   //chiama l'aggiornamento
    		for (int ind = 0; ind < Mappa[x][y].AnimaliVivi.size(); ind++)
    			Mappa[x][y].AnimaliVivi[ind].GetModel()->
    			AggStatVivi(Mappa[x][y].AnimaliVivi[ind]);  //argomento: il chiamante 
    	}
    
    };
    
    std::array<std::array<Casella, Casella::GrMp>, Casella::GrMp> Casella::Mappa;
    Ho cercato di commentare l'esempio per vedere dove non ho capito qualcosa, o se non ho capito niente.
    Grazie.
Devi accedere o registrarti per scrivere nel forum
7 risposte