55 votes

Pourquoi ne puis-je pas déclarer une classe dans un espace de nom comme celui-ci ?

class Namespace::Class;

Pourquoi dois-je faire ça ?

namespace Namespace {
    class Class;
}

En utilisant VC++ 8.0, le compilateur pose des problèmes :

error C2653 : 'Namespace' : n'est pas un nom de classe ou d'espace de nom

Je suppose que le problème ici est que le compilateur ne peut pas dire si Namespace est une classe ou un espace de nom ? Mais pourquoi cela a-t-il de l'importance puisqu'il s'agit juste d'une déclaration en avant ?

Existe-t-il un autre moyen de déclarer une classe définie dans un espace de noms ? La syntaxe ci-dessus donne l'impression de "rouvrir" l'espace de noms et d'étendre sa définition. Et si Class n'ont pas été réellement définis dans Namespace ? Cela entraînerait-il une erreur à un moment donné ?

50voto

John Dibling Points 56814

Vous obtenez des réponses correctes, laissez-moi juste essayer de reformuler :

class Namespace::Class;

Pourquoi dois-je faire ça ?

Vous devez le faire parce que le terme Namespace::Class c'est dire au compilateur :

...OK, compilateur. Allez trouver le namespace nommé Namespace, et à l'intérieur qui fait référence à la classe nommée Class.

Mais le compilateur ne sait pas de quoi vous parlez car il ne connaît pas d'espace de nom nommé Namespace. Même s'il y avait un espace de nom nommé Namespace, comme dans :

namespace Namespace
{
};

class Namespace::Class;

cela ne fonctionnerait toujours pas, car vous ne pouvez pas déclarer une classe dans un espace de noms depuis l'extérieur de cet espace de noms. Vous devez être dans l'espace de noms.

Ainsi, vous pouvez en fait déclarer une classe dans un espace de nom. Il suffit de faire ceci :

namespace Namespace
{
    class Class;
};

40voto

AndreyT Points 139512

Parce que c'est impossible. Dans le langage C++, les noms entièrement qualifiés ne sont utilisés que pour se référer à existant (c'est-à-dire des entités précédemment déclarées). Ils ne peuvent pas être utilisés pour introduire nouveau entités.

Et vous sont en fait "rouvrir" l'espace de nom pour déclarer de nouvelles entités. Si la classe Class est ensuite définie comme un membre d'un espace de noms différent - il s'agit d'une classe complètement différente qui n'a rien à voir avec celle que vous avez déclarée ici.

Une fois que vous avez atteint le point de définir la classe pré-déclarée, vous n'avez pas besoin de "rouvrir" l'espace de noms à nouveau. Vous pouvez la définir dans l'espace de noms global (ou dans tout espace de noms englobant la classe Namespace ) comme

class Namespace::Class {
  /* whatever */
};

Puisque vous faites référence à une entité qui a déjà été déclarée dans l'espace de noms Namespace vous pouvez utiliser un nom qualifié Namespace::Class .

13voto

Martin Points 481

Le type d'une variable déclarée en avant ne serait pas clair. La déclaration forward class Namespace::Class; pourrait signifier

namespace Namespace {
  class Class;
}

o

class Namespace {
public:
  class Class;
};

7voto

Daniel A. White Points 91889

C'est ainsi que la norme C++ est écrite.

3voto

Igor Zevaka Points 32586

Je suppose que c'est pour la même raison que vous ne pouvez pas déclarer des espaces de noms imbriqués en une seule fois comme ceci :

namespace Company::Communications::Sockets {
}

et tu dois faire ça :

namespace Company {
  namespace Communications {
    namespace Sockets {
    }
  }
}

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