Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 20
  1. #1
    Utente di HTML.it L'avatar di gaten
    Registrato dal
    Jul 2007
    Messaggi
    1,269

    [C++] inserimento ed estrazione struttura map

    Ragazzi sono alle prese con questo problema e non riesco a capire perchè.

    codice:
    class Entity {
        public:
            template <class T> void addComponent(){
                T *newComponent = new T();
    
    
                this->mComponents[type_index(typeid(T))] = newComponent;
                newComponent->entity = this;
                newComponent->init();
            }
    
    
    
    
    
    
            template <class T> T* getComponent(){
                if (this->mComponents.count(type_index(typeid(T))) > 0)
                    return static_cast<T*>(this->mComponents[type_index(typeid(T))]);
                else
                    return NULL;
            }
        private:
            map<type_index, IComponent*> mComponents;
    }
    
    
    int main() {
        Entity *test = new Entity();
    
    
        // qui non stampa "ok" poichè non trova alcun elemento con quel indice.
        if (test->mComponents.count(type_index(typeid(AI_followTarget))) > 0)
            cout << "ok";
    
    
        // QUI DOVREBBE DARE ERRORE, 
        // test->getComponent<AI_followTarget>() dovrebbe restituire NULL dato che
        // non l'ho inserito nella mappa
        // invece mi stampa "ciao sei in test()"(metodo per testare)
        test->getComponent<AI_followTarget>()->test();
    
    
        system("pause");
        return 0;
    }
    Dove ho commentato nel main , mi restituisce un elemento che io nella mappa non ho
    inserito. Come mai lo trova comunque??

    Grazie anticipatamente.
    Con i sogni possiamo conoscere il futuro...

  2. #2
    Ricorda che dereferenziare NULL non ti garantisce un errore - semplicemente vai in "undefined behavior", per cui potrebbe succedere qualunque cosa. Con ogni probabilità getComponent ti sta restituendo NULL, ma dato che test() non usa il this non vedi alcun comportamento anomalo.
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Utente di HTML.it L'avatar di gaten
    Registrato dal
    Jul 2007
    Messaggi
    1,269
    Per ora nella classe "AI_followTarget" ho il seguente metodo:

    codice:
    void AI_followTarget::test() {
    	cout << "Ciao mi hai beccato";
    }
    test() dovrebbe essere un metodo che va richiamata da una istanza dell'oggetto AI_followTarget. Dunque se getComponent restituisce NULL, allora devo andare in errore. Inoltre ho provato a verificare:

    codice:
    	if (test->getComponent<AI_followTarget>() == NULL)
    		cout << "NULL";
    ed effettivamente mi stampa NULL.

    dove sbaglio?


    Nella classe "AI_followTarget" ho provato a scrivere il metodo così:

    codice:
    void test() {
    	cout << "Ciao mi hai beccato";
    }
    e mi dà questo errore:
    codice:
    error LNK2019: riferimento al simbolo esterno "public: void __thiscall AI_followTarget::test(void)" (?test@AI_followTarget@@QAEXXZ) non risolto nella funzione _main
    Con i sogni possiamo conoscere il futuro...

  4. #4
    Quote Originariamente inviata da gaten Visualizza il messaggio
    Per ora nella classe "AI_followTarget" ho il seguente metodo:

    codice:
    void AI_followTarget::test() {
    	cout << "Ciao mi hai beccato";
    }
    test() dovrebbe essere un metodo che va richiamata da una istanza dell'oggetto AI_followTarget. Dunque se getComponent restituisce NULL, allora devo andare in errore. Inoltre ho provato a verificare:

    codice:
    	if (test->getComponent<AI_followTarget>() == NULL)
    		cout << "NULL";
    ed effettivamente mi stampa NULL.

    dove sbaglio?
    Sbagli nel pensare che richiamando un metodo su un puntatore NULL allora necessariamente avrai un errore. Non è così; C++ non è Java, non c'è un controllo prima di ogni chiamata tramite puntatore che verifica se this è NULL. Se un metodo accede a dati di istanza della classe (o è virtual e il compilatore non riesce a risolvere la chiamata a compile time) allora con ogni probabilità avrai un errore, visto che si ha un accesso al this (per accedere al membro o alla vtable), altrimenti può darsi che il metodo venga richiamato e apparentemente non ci sia alcun problema (come nel tuo caso - il che si spiega facilmente dato che il tuo metodo non accede al this).

    Come detto sopra, per quanto concerne lo standard C++ richiamare un metodo su un puntatore NULL è undefined behavior, ovvero il compilatore è libero di generare codice che faccia qualunque cosa in tale caso - e nel "qualunque cosa" è anche compreso il "sembra che tutto funzioni correttamente".

    Se vuoi un errore garantito, invece di restituire NULL solleva un'eccezione.
    Amaro C++, il gusto pieno dell'undefined behavior.

  5. #5
    Utente di HTML.it L'avatar di gaten
    Registrato dal
    Jul 2007
    Messaggi
    1,269
    Dunque se ho capito bene o sollevo un exception oppure faccio una cosa del tipo:

    [CODE]
    If ( test->getComponent<AI_followTarget>() != NULL )
    test->getComponent<AI_followTarget>()->test();
    [CODE]

    ??
    Con i sogni possiamo conoscere il futuro...

  6. #6
    Utente di HTML.it L'avatar di gaten
    Registrato dal
    Jul 2007
    Messaggi
    1,269
    Dunque se ho capito bene o sollevo un exception oppure faccio una cosa del tipo:

    codice:
    If ( test->getComponent<AI_followTarget>() != NULL ) 
       test->getComponent<AI_followTarget>()->test();
    ??
    Con i sogni possiamo conoscere il futuro...

  7. #7
    Esatto, magari scrivendolo in maniera un filo più compatta (e evitando di chiamare inutilmente la getComponent due volte):
    codice:
    if(AI_followTarget *ptr=test->getComponent<AI_followTarget>()) 
       ptr->test();
    Tra l'altro, puoi ottimizzare anche la getComponent per evitare di fare due lookup nella mappa inutilmente:
    codice:
            template <class T> T* getComponent(){
                map<type_index, IComponent*>::iterator it=
                    this->mComponents.find(type_index(typeid(T)));
                if (it!=this->mComponents.end())
                    return static_cast<T*>(it->second);
                else
                    return NULL;
            }
    Amaro C++, il gusto pieno dell'undefined behavior.

  8. #8
    Utente di HTML.it L'avatar di gaten
    Registrato dal
    Jul 2007
    Messaggi
    1,269
    Ho visto che puo anche essere usato:
    codice:
    assert(test->getComponent...);
    .. oppure ancora..
    codice:
    Try{
       Test->getComp...
    } catch(..// quu che metto?? Per sollevare un eccezione quandoricevo null??)
    Con i sogni possiamo conoscere il futuro...

  9. #9
    Utente di HTML.it L'avatar di gaten
    Registrato dal
    Jul 2007
    Messaggi
    1,269
    Un'altra cosa che mi rende perplesso è:

    codice:
    test->getComponent<AI_followTarget>()
    restituisce NULL, ma poi test() su quale istanza lo richiama? ?? ??

    test() in AI_followTarget è un metodo di istanza.

    ho provato a fare questo O.O:

    codice:
    AI_followTarget *a = NULL;
     a->test();
    mi richiama perfettamente il metodo test() di AI_followTarget
    Ultima modifica di gaten; 13-10-2014 a 00:28
    Con i sogni possiamo conoscere il futuro...

  10. #10
    Quote Originariamente inviata da gaten Visualizza il messaggio
    Ho visto che puo anche essere usato:
    codice:
    assert(test->getComponent...);
    Occhio a non fare confusione... le assert sono check che vengono normalmente inclusi solo nella build di debug, che servono a controllare che precondizioni che il tuo codice dà per scontate siano effettivamente verificate - in altri termini, se il codice non contiene bug una assert non dovrebbe mai fallire. Le assert terminano direttamente il programma, per cui non sono tanto un sistema di gestione degli errori, quanto un modo rapido per fermare tutto (ed eventualmente breakare nel debugger) nel caso in cui nel programma sia successo qualcosa di completamente assurdo.
    .. oppure ancora..
    codice:
    Try{
       Test->getComp...
    } catch(..// quu che metto?? Per sollevare un eccezione quandoricevo null??)
    Per sollevare le eccezioni si usa la throw, ma l'argomento è piuttosto complesso - sicuramente non affrontabile in un post sul forum - per cui ti rimando al tuo libro di C++.
    Amaro C++, il gusto pieno dell'undefined behavior.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.