69 votes

Pourquoi je dois écrire std::cout et pas aussi std::<<

Pourquoi dois-je écrire std::cout pas std::<< dans une ligne de code comme ceci:

#include <iostream>

int main() {
    std::cout << "Hello, world!";
    return 0;
}

cout provient de l' std bibliothèque, et n'est pas << habituellement utilisé pour faire de bits de décalage? Alors, pourquoi n'ai-je pas d'écrire le champ d'application de l'opérateur :: avant <<, car il est également utilisé dans un autre sens? Comment le compilateur sait qu'après l' std::cout, << signifie autre chose?

55voto

dyp Points 19641

Tout d'abord, le compilateur va regarder les types à gauche et à droite de l' <<. std::cout est de type std::ostream, le littéral de chaîne est de type tableau de 15 const char. Que la gauche est de type classe, il sera à la recherche d'une fonction nommée operator<<. La question est, où il va les chercher?

La recherche de ce nom operator<< est un soi-disant non qualifiés de recherche, parce que le nom de la fonction n'est pas qualifié comme std::operator<<. Non qualifiés de recherche pour les noms de fonction invoque l'argument dépendant de recherche. L'argument dépendant de recherche de recherche dans les classes et espaces de noms associés avec les types d'argument.

Lorsque vous incluez <iostream>, une fonction libre de la signature

template<typename traits>
std::basic_ostream<char, traits>& operator<<(std::basic_ostream<char, traits>&,
                                             const char*);

a été déclarée dans l'espace de noms std. Cet espace de noms est associée avec le type d' std::cout, donc cette fonction sera trouvé.

std::ostream est juste un typedef pour std::basic_ostream<char, std::char_traits<char>>, et le tableau de 15 const char peut être converti implicitement à une char const* (pointant vers le premier élément du tableau). Par conséquent, cette fonction peut être appelée avec les deux types d'arguments.

Il y a d'autres surcharges de operator<<, mais la fonction que j'ai mentionné ci-dessus est le meilleur match pour les types d'argument et celui qui est sélectionné dans ce cas.


Un exemple simple de l'argument dépendant de recherche:

namespace my_namespace
{
    struct X {};

    void find_me(X) {}
}

int main()
{
    my_namespace::X x;
    find_me(x);       // finds my_namespace::find_me because of the argument type
}

N. B. cette fonction est un opérateur, la recherche est un peu plus complexe. Il est recherché par qualifiée de recherche dans la portée de le premier argument (si c'est de type de classe), c'est à dire comme une fonction membre. En outre, non qualifié recherche est effectuée, mais en ignorant toutes les fonctions de membre. Le résultat est légèrement différent, car non qualifiés de recherche est en fait comme une procédure en deux étapes, où argument dépendant de recherche est la deuxième étape. Si la première étape trouve une fonction de membre de la deuxième étape n'est pas réalisée, c'est à dire de l'argument-dépendante de la recherche n'est pas utilisé.

Comparer:

namespace my_namespace
{
    struct X
    {
        void find_me(X, int) {}
        void search();
    };
    void find_me(X, double) {}

    void X::search() {
        find_me(*this, 2.5); // only finds X::find_me(int)
        // pure unqualified lookup (1st step) finds the member function
        // argument-dependent lookup is not performed
    }
}

pour:

namespace my_namespace
{
    struct X
    {
        void operator<<(int) {}
        void search();
    };
    void operator<<(X, double) {}

    void X::search() {
        *this << 2.5; // find both because both steps are always performed
        // and overload resolution selects the free function
    }
}

9voto

P0W Points 21239

En std::cout << "Hello, world!"; //calls std:::operator <<

Ceci est réalisé avec l'Argument-dépendante de recherche de nom (ADL, aka Koenig de Recherche)

Bien que nous n'avons qu'un std qualificatif, mais il ya deux choses qui s' std d'espace de noms

  • cout
  • <<

Sans ADL, (Koenig de Recherche)

std::cout std:: << "Hello World" ;//this won't compile

Pour le compiler, nous avons besoin de l'utiliser de plus en plus laide du formulaire

std::operator<<(std::cout, "Hello, world!");

Donc, pour éviter un tel laid syntaxe nous devons apprécier Koenig Recherche :)

3voto

alecb Points 2179

Le compilateur voit que les arguments de << sont un std::ostream objet et une chaîne, et est donc en mesure de localiser le bon opérateur<< définition sur cette base.

Vous pouvez sorte de penser les types d'argument d'un opérateur (ou vraiment, toute fonction) comme partie de son nom.

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