66 votos

También ¿Por qué tengo que escribir std :: cout y no std :: <<

¿Por qué tengo que escribir std::cout y no también std::<< en una línea de código como este:

#include <iostream>

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

cout proviene std biblioteca, y no es << utiliza generalmente para hacer los bits de desplazamiento? Así que, ¿por qué no tengo que escribir el operador de ámbito :: también antes <<, ya que también se usa con otro significado? Como el compilador sabe que, después std::cout, << significa otra cosa?

55voto

dyp Puntos 19641

En primer lugar, el compilador vistazo a los tipos a la izquierda y a la derecha de <<. std::cout es de tipo std::ostream, el literal de cadena es de tipo array de 15 const char. Como la izquierda es del tipo de clase, se busca una función denominada operator<<. La pregunta es, ¿dónde se verá?

La búsqueda de este nombre operator<< es lo que se denomina incondicional de búsqueda, debido a que el nombre de la función no está calificado como std::operator<<. Sin calificar búsqueda de nombres de función invoca argumento-dependiente de la búsqueda. El argumento de la búsqueda dependiente de la búsqueda en las clases y espacios de nombres asociados con los tipos de argumento.

Cuando usted incluya <iostream>, una función libre de la firma

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

ha sido declarado en el espacio de nombres std. Este espacio de nombres está asociado con el tipo de std::cout, por lo tanto, esta función se encuentra.

std::ostream está a sólo un typedef para std::basic_ostream<char, std::char_traits<char>>, y la matriz de 15 const char se puede convertir implícitamente a un char const* (apuntando al primer elemento de la matriz). Por lo tanto, esta función puede ser llamada con los dos tipos de argumentos.

Hay otras sobrecargas operator<<, pero la función que he mencionado anteriormente es el mejor partido para los tipos de argumentos y el seleccionado en este caso.


Un simple ejemplo de argumento dependiente de la búsqueda:

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. Ya que esta función es un operador, la actual búsqueda es un poco más complejo. Se busca a través calificado de búsqueda en el ámbito de la primer argumento (si es del tipo de clase), es decir, como una función miembro. Además, sin calificar se realiza la búsqueda, pero haciendo caso omiso de todas las funciones miembro. El resultado es un poco diferente, porque no cualificados de búsqueda es en realidad como un procedimiento en dos etapas, donde la búsqueda dependiente de argumentos es el segundo paso. Si el primer paso se encuentra un miembro de la función, el segundo paso no se realiza, es decir, dependiente de argumento de búsqueda es que no utiliza.

Comparar:

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
    }
}

a:

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 Puntos 21239

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

Esto se logra con el Argumento dependiente de búsqueda de nombre (ADL, también conocido como Búsqueda de Koenig)

Aunque sólo tenemos un std calificador, pero hay dos cosas que se nos viene encima a partir de std de espacio de nombres

  • cout
  • <<

Sin ADL, (Búsqueda de Koenig)

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

Para compilarlo, necesitamos utilizar más fea forma

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

Por lo que para evitar tales feo sintaxis debemos apreciar Búsqueda de Koenig :)

3voto

alecb Puntos 2179

El compilador ve que los argumentos a << son un objeto std :: ostream y una cadena, y así es capaz de localizar el operador adecuado << definición basada en esto.

Puede especie de pensar en los tipos de argumentos de un operador (o realmente, cualquier función) como parte de su nombre.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by: