Visualizzazione dei risultati da 1 a 6 su 6
  1. #1
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826

    [c++]riferimenti circolari

    Ciao.
    Una breve domanda:
    Piu' di una volta mi sono trovato a combattere coi riferimenti circolari degli include e il #pragma once per es. non è sempre la soluzione.
    Molte volte ho risolto semplicemente inserendo
    codice:
    class <nomeclassedaincludere>;
    prima della dichiarazione della classe.
    Ma esiste un metodo piu' chiaro per evitare i riferimanti circolari?
    Voi come fate?
    Grazie.

  2. #2
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Dipende da cosa hai scritto e come lo hai scritto.

    In casi estremi basta usare un forward reference e un puntatore (che il compilatore sa sempre come istanziare).
    Ad esempio:
    codice:
     TestA {
         TestB b;
      };
    
      TestB {
          TestA a;
       };
    diventa:
    codice:
      TestB*; 
     TestA {
         TestB* b; // ovviamente qualcuno lo dovrà allocare e deallocare.
      };
    
      TestB {
          TestA a;
       };
    
       // funzioni di classe o struttura qui sotto.
    Tra l'altro si usa spesso per implementare l'idioma pimpl.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  3. #3
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    grazie shodan,
    ma dichiarare un class <nomeclasse> è una cosa simile o la stessa cosa?
    cos' è l'idioma pimpl?
    grazie.

  4. #4
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    No, è una cosa diversa. Nel primo caso dichiari un semplice forward reference ( in cui ricadi nel primo caso che ti ho illustrato e che ho scritto anche sbagliato, ero un pò di fretta.) e in cui non puoi fare qualcosa del genere.
    codice:
    struct TestB;
    
    struct TestA {
    	TestB b; // da errore qui.
    };
    
    struct TestB {
    	TestA a;
    };
    perché il compilatore quando proverà ad istanziare un oggetto TestA, non sa come creare un oggetto di tipo TestB e darà errore.
    Se però modifichi così:
    codice:
    struct TestB;
    
    struct TestA {
    	TestB* b; // adesso il compilatore non da errore.
    };
    
    struct TestB {
    	TestA a;
    };
    // funzioni di TestA e TestB qui sotto.
    il compilatore quando istanzierà un oggetto di classe TestA, riserverà spazio per un puntatore a TestB, perché sa com'è fatto un puntatore. La fregatura consiste che non si può allocare memoria o usare quel puntatore in funzioni incorporare nella definizione di TestA, ma solo dopo che entrambe le classi sono note al compilatore ( di solito nel .cpp )

    Per quanto riguarda il pimpl. E' un modo utile per nascondere le implementazionie per impedire che un cambiamento a un header file faccia ricompilare tutti i file che lo includono.
    In sostanza si riduce a questo ( che se noti è molto simile a quanto detto prima);
    codice:
    struct pimpl;
    
    struct TestA {
    	TestA();
    	~TestA();
    	pimpl* b;
    	void print();
    };
    
    //------------------------------------------------------------
    // tutto questo in un file cpp
    struct pimpl {
    	pimpl() : a(10) {}
    	int a;
    };
    TestA::TestA() : b(new pimpl) {}
    TestA::~TestA() { delete b; }
    void TestA::print() { cout << b->a << endl;}
    In questo caso la definizione di pimpl (il nome ovviamente non è vincolante) non esiste fuori dal file cpp in cui è scritta, quindi ogni tentativo di usare quel puntatore al di fuori di quel file si traduce in errore di compilazione. Se poi aggiungi altri dati, funzioni, etc... a pimpl, basterà ricompilare quel file cpp e non tutti gli altri collegati. Il mondo esterno vedrà solo TestA come intefaccia.
    Per riferimenti:
    http://en.wikipedia.org/wiki/Opaque_pointer
    http://gotw.ca/gotw/028.htm
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  5. #5
    Utente di HTML.it
    Registrato dal
    Jun 2003
    Messaggi
    4,826
    grande!

  6. #6
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Chi?
    Di mio non c'è nemmeno il sacco oltre alla farina.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

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 © 2026 vBulletin Solutions, Inc. All rights reserved.