Domanda

E 'possibile inoltrare-dichiarare una classe annidata, quindi utilizzare come tipo di cemento (non puntatore / riferimento a) membro di dati della classe esterna?

cioè.

class Outer;

class Outer::MaybeThisWay   // Error: Outer is undefined
{
};

class Outer
{
 MaybeThisWay x;

 class MaybeThatOtherWay;

 MaybeThatOtherWay y;   // Error: MaybeThatOtherWay is undefined
};
È stato utile?

Soluzione

Non puoi avanti dichiarare una classe annidata del genere.

A seconda di quello che stai cercando di fare, forse è possibile utilizzare uno spazio dei nomi, piuttosto che una classe sullo strato esterno. È possibile inoltrare-dichiarare una tale classe non è un problema:

namespace Outer {
   struct Inner; 
};

Outer::Inner* sweets;  // Outer::Inner is incomplete so 
                       // I can only make a pointer to it

Se il vostro esterno deve assolutamente essere una classe, e non si può calzascarpe in uno spazio dei nomi, quindi avrete bisogno per esterno per essere un tipo completo nel contesto in cui si dichiara avanti interno.

class Outer
{
   class Inner;  // Inner forward-declared
};  // Outer is fully-defined now

Outer yes;  // Outer is complete, you can make instances of it
Outer::Inner* fun;  // Inner is incomplete, you can only make 
                    // pointers/references to it

class Outer::Inner 
{
};  // now Inner is fully-defined too

Outer::Inner win;  // Now I can make instances of Inner too

Altri suggerimenti

Non c'è modo di dichiarare in avanti una classe annidata senza specificare completamente la classe che contiene. Questo piccolo trucco risolve un pò il problema se

class Outer_Inner
{
};

class Outer
{
public:
   typedef Outer_Inner Inner;
};

Questo funziona per me, come nel mio Outer_Inner convenzione di denominazione non è un nome di classe valida, quindi è ovvio che si riferisce a una classe annidata.

non è ancora possibile in avanti dichiarare la classe annidata in questo modo:

class Outer::Inner;

Ma almeno può essere avanti dichiarato con:

class Outer_Inner;

Se non ti piace il modo in cui Outer_Inner aspetto si potrebbe adottare una convenzione di denominazione per le classi nidificate che meglio si adatta ai vostri gusti. Outer__Inner, Outer_nested_Inner, ecc.

No, ma cosa c'è di sbagliato con il

class Outer {
public:  //or protected or private
    class Inner {
    };

private:
    Inner foo;
};

Inoltra dichiarando non ha senso qui, a meno che mi manca qualcosa (il che è possibile vedere come la tua domanda è carente in un sacco di dettagli)

Ricordate, se una classe è dichiarata in avanti allora si può solo dichiarare riferimenti a o puntatori a un oggetto di tipo forward dichiarato. Non si può fare qualsiasi altra cosa con esso, compreso l'accesso ai suoi membri o funzioni.

Se una classe è stata dichiarata in avanti (ma non hanno ancora la definizione completa) allora si può solo dichiarare un puntatore ad esso, perché il compilatore non sa ancora la dimensione della classe (né i nomi dei suoi campi o metodi).

Se si dichiara un attributo di tipo MaybeThatOtherWay, non un riferimento né un puntatore, il compilatore deve conoscere la definizione completa della classe per determinare la dimensione della classe esterna. Quindi, non è possibile utilizzare la dichiarazione in avanti e quel tipo di dichiarazione di campo, che si tratti di una classe annidata oppure no.

Se avete solo bisogno di un tipo come parametro di funzione o variabile statica, che potrebbe essere fatto sul lato client. Ad esempio, per ricevere la notifica degli eventi da esterno:

Interfaccia:

class Client {
public:
private:
    static void gotIt(int event);
    class Helper;
};

Implementazione:

#include <outer.hpp>

class Client::Helper {
public:
    static void fromOuter(Outer::Inner const& inner) 
    { 
        gotIt(inner.event());
    }
};
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top