Avanti Dichiarazione vs Includono

Considerare i seguenti due scenari (a Cura di, giusto per completare il discorso e renderlo più chiaro)

Caso 1: (non compilare come giustamente indicato qui di seguito)

//B.h
#ifndef B_H
#define B_H
#include "B.h"

class A;

class B { 
        A obj;
        public:
        void printA_thruB();

         };  
#endif

//B.cpp
#include "B.h"
#include <iostream>

void B::printA_thruB(){
        obj.printA();
        }   


//A.h;
#ifndef A_H
#define A_H

#include "A.h"

class A { 
        int a;
        public:
        A();
        void printA();

         };  
#endif   

//A.cpp                           
#include "A.h"                    
#include <iostream>               

A::A(){                           
        a=10;                     
        }                         

void A::printA()                  
{                                 
std::cout<<"A:"<<a<<std::endl;    
}  


//main.cpp
 #include "B.h"
  #include<iostream>
 using namespace std;

 int main()
 {
 B obj;
 obj.printA_thruB();
 }

Caso 2: (il solo modifiche…funziona senza compiliation errore)

//B.h

#include "A.h" //Add this line
//class A;     //comment out this line

Supponiamo sia il A.cpp e B.cpp sono rispettati insieme. Fare due scenari precedenti apportare eventuali differenze? C’è un motivo per preferire un metodo rispetto all’altro?

Modifica:
Allora, come faccio a rendere lo scenario 1, in opera.

  • Così hai compilato A.cpp e B.cpp insieme, ma che cosa hai fatto con A. h e B. h?
  • Fatta la domanda più chiaro per voi
InformationsquelleAutor Sii | 2010-09-03



6 Replies
  1. 13

    Caso 1 produrrà un “tipo incompleto” errore durante la compilazione B.cpp. A causa di classe B contiene una classe di Un oggetto, la definizione (e in particolare le dimensioni) e la classe A è necessario per essere completato prima della definizione della classe B.

    In alternativa, si può scegliere di fare some_variable un puntatore o un riferimento alla classe a, e in tal caso la dichiarazione sarebbe sufficiente, in B. h. Avresti ancora bisogno di una definizione completa di Un in B.cpp (supponendo che hai fatto uso effettivo di Un membro funzioni/dati).

    • Un chiarimento. Caso 1 solo produrre un errore di compilazione se si tenta di chiamare qualsiasi metodi di A. In questo caso si dovrebbe dare un errore dal momento che sarà implicitamente chiama il costruttore. Ma in uno scenario diverso se uno di B metodi semplicemente ricevuto un puntatore a Un oggetto, che si è poi passati a un altro metodo/funzione che era al di fuori di B responsabilità, quindi il compilatore sarebbe bene non conoscere la definizione di A.
    • hai ragione Drew ottengo un Errore di compilazione. Allora, come posso superare questo? Ho pensato di inoltrare le dichiarazioni possono essere utilizzati invece di intestazione di inclusione.
    • No. Caso 1 si producono sempre un errore di compilazione in quanto il compilatore non sa sizeof(A), e quindi non può sapere come lay out a B oggetto.
    • È necessario definire completamente Un (includendo A. h) prima di definire la classe B, o hai bisogno di cambiare a contenere un puntatore o un riferimento a Un raggio di B. In questo caso il facile/soluzione più ovvia è quella di includere A. h in B. h. Perché ti sembra di essere riluttanti a farlo?
    • No.Stavo cercando di ottenere la mia testa intorno in avanti dichiarazione e di assumere, ha fatto la classe accessibile senza incluse le intestazioni…qualcosa di simile a extern.
    • Quasi subito. Dice al compilatore che una classe con quel nome esiste-che è sufficiente a consentire la dichiarazione di un riferimento o un puntatore a quel tipo (ma nient’altro).
    • d’accordo che il caso 1, come definito produrrà un errore di compilazione. Cercando di spiegare che in altri scenari, avanti di dichiarazioni non corrispondenti definizioni potrebbe non causare errori di compilazione per aiutare MrProg imparare di più su di loro.

  2. 11

    Avanti dichiarazione non è un sostituto per l’Intestazione del file di inclusione.

    Come il nome stesso implica, in avanti dichiarazione è solo un Declaration e non una definizione.

    Così, si provvederà a dichiarare dicendo al compilatore che è una classe e ho appena dichiarazione di qui e vi fornirà la definizione quando sto andando a usarlo. Così, normalmente si forward declare nel file di Intestazione e #include nel .file cpp dove si utilizzare i membri dell’attaccante classe dichiarata.

    Così facendo, quello che dovete fare è, ovunque, inclusa l’intestazione del file ci sarà solo una dichiarazione per la classe invece di tutto il contenuto #included

    Ma dopo aver detto che, quando il compilatore richiede la definizione della classe, dovrebbe essere #included..

    Quindi, nel tuo caso A obj; richiede la definizione di class A e, quindi, si dovrebbe #include..

    Io stesso ho chiesto una simile domanda qui e un altro domanda simile che ha anche una bella risposta…

    Speranza che aiuta..

    • Mentre incluse le intestazioni facciamo la stessa cosa..è solo dichiarazione..definizione va in .cpp file di origine. Quindi, se devo cambiare il mio A obj per A *obj che è un puntatore si suppone di lavorare.( ma non)
    • Grazie per l’aiuto..ho confuso abbastanza per un giorno mi pensa.
  3. 4

    È necessario utilizzare forward dichiarazioni nei casi in cui si hanno classi che si richiamano a vicenda.

    //A.h
    
    class B;
    
    class A {
        B* someVar;
    }
    
    //B.h
    #include <A.h>
    
    class B {
        A* someVar;
    }

    Ma non c’è alcun beneficio per farlo nel caso si strutturate.

    • Grazie per le info. se B è l’accesso di alcune variabili di Un nel mio caso.
    • Nel tuo caso vuoi davvero usare l’esplicita inclusione di A. h all’interno di B. h. Ci sono solo due casi che ho visto in avanti i riferimenti utilizzati: il primo che ho citato sopra per quanto riguarda i riferimenti circolari, e il secondo è stato un caso in cui un fornitore ha fornito i file di intestazione che aveva alcune classi definite solo come i riferimenti in avanti. Avevano fregato i loro file di intestazione per proteggere le loro informazioni riservate. Il risultato netto è che è stato un incubo lavorare con loro API — io non lo consiglio.
    • Stavo cercando di fare qualcosa di simile ..rimuovere l’intestazione dell’interfaccia (.h) e avanti dichiarare la classe che sto cercando di utilizzare.
  4. 3

    Pensare come un compilatore. Per creare un A all’interno di B, il compilatore deve sapere come creare un A, e l’unico modo per farlo è quello di avere la completa definizione. Avanti dichiarazione dice al compilatore che la classe A esiste senza descrivere quello che sembra; questo è sufficiente per la definizione di un puntatore o un riferimento. Quando arriva il momento di utilizzare tale puntatore o un riferimento, la definizione di classe completa sarà richiesto.

    • Quindi, se devo includere l’intestazione "A.h" in B.cpp file e solo avanti dichiarare di classe A in B. h non dovrebbe funzionare?
    • no non funziona – B. h definisce come creare un B, ma non è possibile creare un B senza sapere come creare Un perché B contiene un A. È possibile memorizzare un puntatore o un riferimento a Una senza sapere come creare Una a, che è il motivo per cui il riferimento in avanti può essere utile, non solo nel tuo caso.
    • se cambio il A obj per A *obj e fare come ho detto sopra, e anche di fare int a in classe a come pubblico, sono in grado di compilare..ma ottengo l’errore di segmentazione. Così ho gues la mia comprensione di inoltrare la dichiarazione devono essere rethinked.
  5. 2

    Se si vuole ritrarre some_variable come un puntatore, quindi spesso è consigliabile utilizzare avanti dichiarazioni, quando possibile, per evitare il sovraccarico di include e più i tempi di compilazione.

    Sono tutti per le migliori pratiche, ma mi piace molto usare l’Ide che hanno nizza codice di navigazione avanti e causare un problema c’è, almeno con Netbeans. Ogni volta che cerco di passare a una dichiarazione di tipo, finisco sempre in avanti e non .h file contenente l’effettivo dichiarazione. Io sono disposto ad accettare qualche extra in fase di compilazione per la facilità di navigazione. Forse questo è solo un problema con Netbeans 🙂

    .. oh yeah.. Se si guardano le domande relative a destra della tua domanda, troverete un sacco di informazioni aggiuntive del forward dichiarazioni.

    • Questo è quello che stavo cercando di evitare..indesiderati intestazione di inclusione.
  6. 0

    Per il caso 1, il compilatore si lamenta con “tipo incompleto” per la classe B classe B contiene una classe di Un oggetto, e non dirlo a B ogni dettaglio di classe A, in modo compilatore cann ‘ t decidere la dimensione dell’oggetto B.

    Per il vostro caso, è possibile utilizzare A& obj o A* obj invece di A obj, dal momento che la dimensione di riferimento/puntatore const(4/8 per 32bit/64bit CPU).

Lascia un commento