Domanda

Il seguente codice è compilato in VC++6.Non capisco perché io sono sempre l'errore di compilazione C2079: 'b' uses undefined class 'B' per il codice riportato di seguito.

Classe B Fonte

#include "B.h"

void B::SomeFunction()
{
}

Classe B Intestazione

#include "A.h"

struct A;

class B
{
    public:
        A a;
        void SomeFunction();
};

Una struttura di Intestazione

#include "B.h"

class B;

struct A
{
    B b;
};

Se ho cambiato classe B intestazione la seguente, quindi non ci sarà alcun errore.Ma l'intestazione dichiarazione di non essere al top!

Classe B Intestazione con strani intestazione dichiarazione

struct A;

class B
{
     public:
        A a;
        void SomeFunction();
};

#include "A.h"
È stato utile?

Soluzione

Per definire una classe o una struttura, il compilatore deve sapere quanto è grande ogni variabile membro della classe.Avanti e la dichiarazione di non farlo.Ho sempre e solo visto utilizzato per i puntatori e (meno spesso) i riferimenti.

Al di là di quello, quello che stiamo cercando di fare qui non può essere fatto.Non si può avere una classe che contiene un oggetto di un'altra classe B che contiene un oggetto di classe A.Si può, tuttavia, classe A contenere un puntatore la classe B che contiene un oggetto di classe A.

B.cpp

#include "B.h"

void B::SomeFunction()
{
}

B. h

#ifndef __B_h__  // idempotence - keep header from being included multiple times
#define __B_h__
#include "A.h"

class B
{
public:
    A a;
    void SomeFunction();
};

#endif // __B_h__

A. h

#ifndef __A_h__  // idempotence - keep header from being included multiple times
#define __A_h__
#include "B.h"

class B; // forward declaration

struct A
{
    B *b;  // use a pointer here, not an object
};

#endif // __A_h__

Due punti.In primo luogo, essere sicuri di utilizzare una qualche forma di idempotence per mantenere le intestazioni da essere incluso più volte per unità di compilazione.Secondo, cerca di capire che in C++, l'unica differenza tra le classi e le strutture è il livello di visibilità predefinita - classi di uso privato visibilità per impostazione predefinita, mentre le strutture di uso pubblico visibilità per impostazione predefinita.Le seguenti definizioni sono funzionalmente equivalente in C++.

class MyClass
{
public: // classes use private visibility by default
    int i;
    MyClass() : i(13) { }
};

struct MyStruct
{
    int i;
    MyStruct() : i(13) { }
};

Altri suggerimenti

dichiarazioni di andata, come

struct A;

o

class A;

introdurre una come tipo incompleto e rimane incompleta fino al raggiungimento fine della definizione di tipo. Ci sono cose che puoi fare con i tipi incompleti e le cose che non possono. Puoi

  1. Dichiarare variabili (o membri) di tipo "puntatore a" e "riferimento ad un"
  2. Dichiarare funzioni che accettano argomenti di tipo A o di tipo restituito A

Non puoi

  1. Dichiarare variabili (né i membri) di tipo A
  2. puntatori dereference A o accedere a tutti i membri di riferimenti a un
  3. Definisci sottoclassi di A.

Nel codice si tenta di dichiarare membro struct di tipo incompleto. E 'illegale. Solo i puntatori e riferimenti sono ammessi.

public:
    A a;

Si sta cercando di creare l'oggetto di A con la sola dichiarazione anticipata. Compiler in questo momento (solo in avanti decl) non può decidere la dimensione dell'oggetto A e, di conseguenza, non può allocare memoria necessaria per A. Quindi non è possibile creare oggetti con solo in avanti decl.

Invece di sostituire con:

A* a;

puntatore o riferimento a una definizione di classe, senza una volontà funzionare bene.

Due questioni saltare fuori di me qui.

1: Hai scritto Struct A invece di struct A; notare la minuscola "s". Il tuo compilatore potrebbe prendere in considerazione l'equivalente, ma non credo che sia di serie C ++.

È stato definito un riferimento circolare tra il A e B. Ogni Un oggetto deve contenere un oggetto B, ma ogni oggetto B deve contenere un oggetto A! Questa è una contraddizione, e non funzionerà mai il modo in cui si desidera. Il solito modo C ++ per risolvere il problema è quello di utilizzare puntatori o riferimenti per A::b o B::a (o entrambi).

È alse includere A.h da B.h e B.h da A.H. Si dovrebbe almeno utilizzare le macro del preprocessore:

#ifndef __A_H__
#define __A_H__

// A.h contents

#endif

in modo che il file non sarà incluso più di una volta.

Se si crea un'istanza di A, che creerà un'istanza di B (membro var) che creerà un'istanza di A (membro var) che creerà un'istanza di B che creerà un'istanza di A e così via ... Il compilatore non deve permettere che questo poiché richiede memoria infinita.

Per risolvere questo problema, A o B devono utilizzare un riferimento / puntatore alla classe.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top