32 votes

C++ une classe imbriquée/déclaration anticipée problème

Est-il possible de déclarer une classe imbriquée, puis l'utiliser comme le type de béton (pas de pointeur/référence) membre de données de l'extérieur de la classe?

I. E.

class Outer;

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

class Outer
{
 MaybeThisWay x;

 class MaybeThatOtherWay;

 MaybeThatOtherWay y;   // Error: MaybeThatOtherWay is undefined
};

37voto

janks Points 1291

Vous ne pouvez pas l'avant-déclarer une classe imbriquée comme ça.

En fonction de ce que vous essayez de faire, peut-être vous pouvez utiliser un espace de noms plutôt que d'une classe sur la couche externe. Vous pouvez transmettre la déclaration d'une classe, pas de problème:

namespace Outer {
   struct Inner; 
};

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

Si votre Extérieur doit absolument être une classe, et vous ne pouvez pas chausse-pied dans un espace de noms, alors vous aurez besoin pour l'Extérieur pour être complet type dans le contexte où vous déclarer avant Intérieure.

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

15voto

deft_code Points 19418

Il n'y a aucun moyen de le déclarer avant une classe imbriquée sans spécification de la classe conteneur. Ce petit truc un peu résout le problème

class Outer_Inner
{
};

class Outer
{
public:
   typedef Outer_Inner Inner;
};

Cela fonctionne pour moi comme dans ma convention de nommage Outer_Inner n'est pas valide d'un nom de classe, il est donc évident qu'il réfère à une classe imbriquée.

Vous ne pouvez toujours pas déclarer avant la classe imbriquée comme ceci:

class Outer::Inner;

Mais au moins, il peut être déclaré avant avec:

class Outer_Inner;

Si vous n'aimez pas la façon dont Outer_Inner vous regarde pourraient adopter une convention de nommage pour les classes imbriquées qui convient le mieux à votre goût. Outer__Inner, Outer_nested_Inner, etc.

1voto

Glen Points 13521

Non, mais quel est le problème avec

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

private:
    Inner foo;
};

Avant de déclarer ne fait pas de sens ici, à moins que je me manque quelque chose (ce qui est possible de voir que votre question manque dans beaucoup de détails)

Rappelez-vous, si une classe est avant déclara alors vous ne pouvez déclarer les références ou des pointeurs vers un objet du type déclaré. Vous ne pouvez pas faire autre chose avec elle, y compris l'accès à ses membres ou de ses fonctions.

1voto

Ken Bloom Points 27197

Si une classe a été de l'avant-déclarée (mais vous n'avez pas la définition complète encore) alors vous ne pouvez déclarer un pointeur vers elle, parce que le compilateur ne connaît pas encore la taille de la classe (ni les noms de ses champs ou méthodes).

0voto

Seb Points 2117

Si vous déclarez un attribut de type MaybeThatOtherWay, pas une référence ni un pointeur, le compilateur doit connaître la définition complète de la classe pour déterminer la taille de l'extérieur de la classe. Ainsi, vous ne pouvez pas utiliser avant de déclaration et de ce genre de champ de la déclaration, si c'est une classe imbriquée ou pas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X