¿Cuál es el significado de los dos puntos dobles "::" antepuestos?

Resuelto rmbianchi asked hace 13 años • 9 respuestas

Encontré esta línea de código en una clase que tengo que modificar:

::Configuration * tmpCo = m_configurationDB;//pointer to current db

y no sé qué significa exactamente los dos puntos dobles antepuestos al nombre de la clase. Sin eso, leería: declaración de tmpCocomo puntero a un objeto de la clase Configuration... pero los dos puntos dobles antepuestos me confunden.

También encontré:

typedef ::config::set ConfigSet;
rmbianchi avatar Nov 24 '10 23:11 rmbianchi
Aceptado

Esto garantiza que la resolución se produzca desde el espacio de nombres global, en lugar de comenzar en el espacio de nombres en el que se encuentra actualmente. Por ejemplo, si tuviera dos clases diferentes llamadas Configurationasí:

class Configuration; // class 1, in global namespace
namespace MyApp
{
    class Configuration; // class 2, different from class 1
    function blah()
    {
        // resolves to MyApp::Configuration, class 2
        Configuration::doStuff(...) 
        // resolves to top-level Configuration, class 1
        ::Configuration::doStuff(...)
    }
}

Básicamente, le permite atravesar el espacio de nombres global ya que su nombre podría verse afectado por una nueva definición dentro de otro espacio de nombres, en este caso MyApp.

Wyatt Anderson avatar Nov 24 '2010 16:11 Wyatt Anderson

El ::operador se llama operador de resolución de alcance y hace precisamente eso: resuelve el alcance. Entonces, al anteponer un nombre de tipo con esto, le dice a su compilador que busque el tipo en el espacio de nombres global.

Ejemplo:

int count = 0;

int main(void) {
  int count = 0;
  ::count = 1;  // set global count to 1
  count = 2;    // set local count to 2
  return 0;
}
Moo-Juice avatar Nov 24 '2010 16:11 Moo-Juice

Ya hay muchas respuestas razonables. Voy a aportar una analogía que puede ayudar a algunos lectores. ::Funciona de manera muy similar al separador de directorios del sistema de archivos ' /', cuando busca en su ruta un programa que le gustaría ejecutar. Considerar:

/path/to/executable

Esto es muy explícito: sólo un ejecutable en esa ubicación exacta en el árbol del sistema de archivos puede coincidir con esta especificación, independientemente de la RUTA vigente. Similarmente...

::std::cout

...es igualmente explícito en el "árbol" del espacio de nombres de C++.

En contraste con estas rutas absolutas, puedes configurar buenos shells UNIX (por ejemplo, zsh ) para resolver rutas relativas en tu directorio actual o cualquier elemento en tu PATHvariable de entorno, por lo que si PATH=/usr/bin:/usr/local/biny estabas "en" /tmp, entonces...

X11/xterm

...correría felizmente /tmp/X11/xtermsi lo encontraran, de lo contrario /usr/bin/X11/xterm, de lo contrario /usr/local/bin/X11/xterm. De manera similar, supongamos que estaba en un espacio de nombres llamado Xy tenía un " using namespace Y" vigente, entonces...

std::cout

... podría encontrarse en cualquiera de ::X::std::cout, ::std::cout, ::Y::std::couty posiblemente en otros lugares debido a la búsqueda dependiente de argumentos (ADL, también conocida como búsqueda de Koenig). Entonces, only ::std::coutes realmente explícito sobre exactamente a qué objeto te refieres, pero afortunadamente nadie en su sano juicio crearía su propia clase/estructura o espacio de nombres llamado " " std, ni nada llamado " cout", por lo que en la práctica usar only std::coutestá bien.

Diferencias destacables :

1) los shells tienden a usar la primera coincidencia usando el orden en PATH, mientras que C++ genera un error de compilación cuando ha sido ambiguo.

2) En C++, los nombres sin ningún ámbito principal pueden coincidir en el espacio de nombres actual, mientras que la mayoría de los shells de UNIX solo lo hacen si se coloca .el archivo PATH.

3) C++ siempre busca en el espacio de nombres global (como tener /implícitamente su PATH).

Discusión general sobre espacios de nombres y carácter explícito de los símbolos.

El uso de "rutas" absolutas ::abc::def::...a veces puede ser útil para aislarlo de otros espacios de nombres que esté usando, parte de los cuales no tiene control sobre el contenido, o incluso otras bibliotecas que el código cliente de su biblioteca también usa. Por otro lado, también lo acopla más estrechamente a la ubicación "absoluta" existente del símbolo, y pierde las ventajas de la coincidencia implícita en espacios de nombres: menos acoplamiento, movilidad más fácil del código entre espacios de nombres y código fuente más conciso y legible. .

Como ocurre con muchas cosas, es un acto de equilibrio. El estándar C++ incluye muchos identificadores std::que son menos "únicos" que cout, que los programadores podrían usar para algo completamente diferente en su código (por ejemplo merge, includes, fill, generate, exchange, queue, toupper, max). Dos bibliotecas no estándar no relacionadas tienen muchas más posibilidades de utilizar los mismos identificadores, ya que los autores generalmente no se conocen entre sí. Y las bibliotecas, incluida la biblioteca estándar de C++, cambian sus símbolos con el tiempo. Todo esto crea potencialmente ambigüedad al recompilar código antiguo, particularmente cuando ha habido un uso intensivo de using namespaces: lo peor que puede hacer en este espacio es permitir que using namespacelos s en los encabezados escapen de sus alcances, de modo que una cantidad arbitrariamente grande de mensajes directos e indirectos El código del cliente no puede tomar sus propias decisiones sobre qué espacios de nombres usar y cómo gestionar las ambigüedades.

Entonces, un líder ::es una herramienta en la caja de herramientas del programador de C++ para eliminar activamente la ambigüedad de un conflicto conocido y/o eliminar la posibilidad de ambigüedad futura...

Tony Delroy avatar Nov 24 '2010 16:11 Tony Delroy

::es el operador de resolución de alcance. Se utiliza para especificar el alcance de algo.

Por ejemplo, ::solo está el alcance global, fuera de todos los demás espacios de nombres.

some::thingpuede interpretarse de cualquiera de las siguientes maneras:

  • somees un espacio de nombres (en el ámbito global o en un ámbito externo al actual) y thinges un tipo , una función , un objeto o un espacio de nombres anidado ;
  • somees una clase disponible en el ámbito actual y thinges un objeto miembro , función o tipo de la someclase;
  • en una función miembro de clase , somepuede ser un tipo base del tipo actual (o el tipo actual mismo) y thingluego es un miembro de esta clase, un tipo , función u objeto .

También puede tener un alcance anidado, como en some::thing::bad. Aquí cada nombre podría ser un tipo, un objeto o un espacio de nombres. Además, la última, badtambién podría ser una función. Los demás no pudieron, ya que las funciones no pueden exponer nada dentro de su alcance interno.

Entonces, volviendo a su ejemplo, ::thingsolo puede ser algo en el ámbito global: un tipo, una función, un objeto o un espacio de nombres.

La forma en que lo usa sugiere (usado en una declaración de puntero) que es un tipo en el ámbito global.

Espero que esta respuesta sea lo suficientemente completa y correcta para ayudarlo a comprender la resolución del alcance.

Klaim avatar Nov 24 '2010 16:11 Klaim

::se utiliza para vincular algo (una variable, una función, una clase, un typedef, etc.) a un espacio de nombres o a una clase.

Si no hay un lado izquierdo antes ::, entonces subraya el hecho de que está utilizando el espacio de nombres global.

p.ej:

::doMyGlobalFunction();

Stephane Rolland avatar Nov 24 '2010 16:11 Stephane Rolland