web-dev-qa-db-fra.com

Utiliser :: en C++

J'apprends le C++ et je ne peux jamais dire quand j'ai besoin d'utiliser ::. Je sais que je dois utiliser std:: devant cout et cin. Cela signifie-t-il qu'à l'intérieur du fichier iostream, les développeurs qui l'ont créé ont créé un espace de noms appelé std et placé les fonctions cin et cout dans l'espace de noms appelé std? Lorsque j'ai créé une nouvelle classe qui ne se trouve pas dans le même fichier que main(), pour une raison quelconque, je dois ajouter ::.

Par exemple, si je crée une class appelée A, pourquoi dois-je mettre A:: devant une fonction que je crée, même si je ne l'ai pas mise dans un nom de domaine? Par exemple, void A::printStuff(){}. Si je crée une fonction dans main, pourquoi ne dois-je pas mettre main::printStuf{}?

Je sais que ma question est probablement déroutante, mais quelqu'un pourrait-il m'aider?

25
foobar5512

Vous avez à peu près raison sur cout et cin. Ce sont des objets (pas des fonctions) définis dans l’espace de noms std. Voici leurs déclarations telles que définies par le standard C++:

En-tête <iostream> synopsis

#include <ios>
#include <streambuf>
#include <istream>
#include <ostream>

namespace std {
  extern istream cin;
  extern ostream cout;
  extern ostream cerr;
  extern ostream clog;

  extern wistream wcin;
  extern wostream wcout;
  extern wostream wcerr;
  extern wostream wclog;
}

:: est connu en tant qu'opérateur de résolution scope. Les noms cout et cin sont définis dans std, nous devons donc qualifier leurs noms avec std::.

Les classes se comportent un peu comme des espaces de noms en ce sens que les noms déclarés à l'intérieur de la classe appartiennent à la classe. Par exemple:

class foo
{
  public:
    foo();
    void bar();
};

Le constructeur nommé foo est un membre de la classe nommée foo. Ils ont le même nom parce que c'est le constructeur. La fonction bar est également membre de foo.

Comme ils sont membres de foo, lorsque vous faites référence à eux en dehors de la classe, nous devons qualifier leurs noms. Après tout, ils appartiennent à cette classe. Donc, si vous voulez définir le constructeur et bar en dehors de la classe, vous devez le faire comme suit:

foo::foo()
{
  // Implement the constructor
}

void foo::bar()
{
  // Implement bar
}

C'est parce qu'ils sont définis en dehors de la classe. Si vous n'aviez pas mis la qualification foo:: sur les noms, vous définiriez de nouvelles fonctions dans la portée globale, plutôt que d'être membres de foo. Par exemple, ceci est entièrement différent de bar:

void bar()
{
  // Implement different bar
}

Il est autorisé à porter le même nom que la fonction dans la classe foo car sa portée est différente. Cette bar est dans la portée globale, alors que l'autre bar appartenait à la classe foo.

41
Joseph Mansfield

Les :: sont utilisés pour déréférencer les étendues.

const int x = 5;

namespace foo {
  const int x = 0;
}

int bar() {
  int x = 1;
  return x;
}

struct Meh {
  static const int x = 2;
}

int main() {
  std::cout << x; // => 5
  {
    int x = 4;
    std::cout << x; // => 4
    std::cout << ::x; // => 5, this one looks for x outside the current scope
  }
  std::cout << Meh::x; // => 2, use the definition of x inside the scope of Meh
  std::cout << foo::x; // => 0, use the definition of x inside foo
  std::cout << bar(); // => 1, use the definition of x inside bar (returned by bar)
}

non liées: cout et cin ne sont pas des fonctions, mais des occurrences d'objets de flux.

EDIT corrigé comme Keine Lust suggéré

14
scones

Le :: est appelé opérateur de résolution de portée. Peut être utilisé comme ceci:

::identifiant
nom-classe::identifiant
namespace::identifier

Vous pouvez lire à ce sujet ici
https://docs.Microsoft.com/en-us/cpp/cpp/scope-resolution-operator?view=vs-2017

10
Johnny Mnemonic

L'une des utilisations de 'Unary Scope Resolution Operator' ou 'Colon Colon Colon' est la sélection de variables locales et globales de noms identiques:

    #include <iostream>
    using namespace std;

    int variable = 20;

    int main()
    {
    float variable = 30;

    cout << "This is local to the main function: " << variable << endl;
    cout << "This is global to the main function: " << ::variable << endl;

    return 0;
    }

La sortie résultante serait:

Ceci est local à la fonction principale: 30

C'est global pour la fonction principale: 20

Les autres utilisations possibles sont les suivantes: définir une fonction extérieure à une classe, accéder à une variable statique dans une classe ou utiliser plusieurs héritages.

2
TrevorLee

regardez-le est informatif [Identifiants qualifiés

Une expression id qualifiée est une expression id non qualifiée précédée d'un opérateur de résolution de portée ::, et éventuellement d'une séquence d'énumération, de noms de classe ou d'espaces de noms (depuis C++ 11) ou d'expressions decltype (depuis C++ 11) séparées par les opérateurs de résolution de portée. Par exemple, l'expression std :: string :: npos est une expression qui nomme le membre statique npos dans la chaîne de classe dans namespace std. L'expression :: tolower nomme la fonction tolower dans l'espace de noms global. L'expression :: std :: cout nomme la variable globale cout dans namespace std, qui est un espace de noms de niveau supérieur. L'expression boost :: signs2 :: connection nomme le type de connexion déclaré dans les signaux d'espace de noms2, qui est déclaré dans l'extension de l'espace de noms.

Le modèle de mot clé peut apparaître dans les identificateurs qualifiés si nécessaire pour lever la ambiguïté des noms de modèles dépendants] 1

0
vincent87