c++ - signos - uso de los puntos suspensivos
¿Cuál es el significado de dos puntos prepintados “::”? (8)
(Esta respuesta es principalmente para los usuarios de Google, porque OP ya resolvió su problema). El significado de operador de resolución de alcance prependido - se ha descrito en otras respuestas, pero me gustaría agregar por qué la gente lo está utilizando.
El significado es "tomar el nombre del espacio de nombres global, no otra cosa". Pero, ¿por qué esto debería ser escrito explícitamente?
Caso de uso - choque de espacio de nombres
Cuando tenga el mismo nombre en el espacio de nombres global y en el espacio de nombres local / anidado, se utilizará el local. Así que si quieres el global, prepéndelo con ::
. Este caso fue descrito en la respuesta de @Wyatt Anderson, por favor vea su ejemplo.
Caso de uso - enfatizar la función no miembro
Cuando escribe una función miembro (un método), las llamadas a otra función miembro y las llamadas a funciones no miembros (gratuitas) son similares:
class A {
void DoSomething() {
m_counter=0;
...
Twist(data);
...
Bend(data);
...
if(m_counter>0) exit(0);
}
int m_couner;
...
}
Pero puede suceder que Twist
sea una función miembro hermana de la clase A
, y Bend
es una función gratuita. Es decir, Twist
puede usar y modificar m_couner
y Bend
no. Entonces, si quiere asegurarse de que m_counter
permanezca en 0, debe marcar Twist
, pero no necesita marcar Bend
.
Entonces, para que esto se destaque más claramente, uno puede escribir this->Twist
para mostrar al lector que Twist
es una función miembro o escribir ::Bend
para mostrar que Bend
está libre. O ambos. Esto es muy útil cuando estás haciendo o planificando una refactorización.
Encontré esta línea de un código en una clase que debo modificar:
::Configuration * tmpCo = m_configurationDB;//pointer to current db
y no sé qué significa exactamente los dos puntos dobles ante el nombre de la clase. Sin eso, leería: declaración de tmpCo
como un puntero a un objeto de la clase Configuration
... pero el doble de dos puntos antepuesto me confunde.
También encontré:
typedef ::config::set ConfigSet;
El operador ::
se llama el operador de resolución de alcance y hace exactamente eso, resuelve el alcance. Entonces, al prefijar 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;
}
Esto garantiza que la resolución se realice desde el espacio de nombres global, en lugar de comenzar con el espacio de nombres en el que se encuentra actualmente. Por ejemplo, si tenía dos clases diferentes llamadas Configuration
como tal:
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 recorrer hasta el espacio de nombres global, ya que su nombre puede verse afectado por una nueva definición dentro de otro espacio de nombres, en este caso MyApp
.
Muchas respuestas razonables ya. Voy a agregar una analogía que puede ayudar a algunos lectores. ::
funciona muy parecido al separador de directorios del sistema de archivos '' /
'', al buscar en su ruta un programa que le gustaría ejecutar. Considerar:
/path/to/executable
Esto es muy explícito: solo un ejecutable en esa ubicación exacta en el árbol del sistema de archivos puede coincidir con esta especificación, independientemente del PATH en efecto. Similar...
::std::cout
... es igualmente explícito en el "árbol" de espacio de nombres de C ++.
En contraste con dichas rutas absolutas, puede configurar buenas shells de UNIX (por ejemplo, zsh) para resolver rutas relativas bajo cualquier elemento en su PATH
entorno PATH
, por lo que si PATH=/usr/bin:/usr/local/bin
, entonces ...
X11/xterm
... felizmente ejecutaría /usr/bin/X11/xterm
si se encuentra, de lo contrario /usr/local/bin/X11/xterm
. De manera similar, digamos que estaba en un espacio de nombres llamado X
, y tenía un " using namespace Y
" en efecto, entonces ...
std::cout
... se puede encontrar en cualquiera de ::X::std::cout
, ::std::cout
, ::Y::std::cout
, y posiblemente en otros lugares debido a la búsqueda dependiente del argumento (ADL, aka Búsqueda Koenig). Entonces, solo ::std::cout
es realmente explícito sobre exactamente a qué objeto te refieres, pero afortunadamente nadie en su sano juicio creará su propia clase / estructura o espacio de nombres llamado " std
", ni nada llamado " cout
", por lo que practicar usando solo std::cout
está bien.
(Una diferencia notable es que los shells tienden a usar la primera coincidencia usando el ordenamiento en PATH
, mientras que C ++ da un error de compilación cuando ha sido ambiguo).
Discusión general sobre espacios de nombres y explicitación de símbolos.
El uso de absolute ::abc::def::...
"rutas" a veces puede ser útil para aislarlo de cualquier otro espacio de nombre que esté usando, parte del cual no tenga control sobre el contenido o incluso otras bibliotecas. que también utiliza el código de cliente de su biblioteca. 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 los espacios de nombres: menos acoplamiento, más fácil movilidad del código entre los espacios de nombres y un código fuente más conciso y legible. .
Como con muchas cosas, es un acto de equilibrio. El estándar de C ++ coloca muchos identificadores bajo 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
, toupper
queue
, toupper
, max
). Dos bibliotecas no estándar no relacionadas tienen una posibilidad mucho mayor de usar los mismos identificadores, ya que los autores generalmente no están o están menos informados entre sí. Y las bibliotecas, incluida la biblioteca estándar de C ++, cambian sus símbolos a lo largo del tiempo. Todo esto potencialmente crea ambigüedad al recompilar el código antiguo, particularmente cuando se usa mucho el uso de los using namespace
de using namespace
: lo peor que puede hacer en este espacio es permitir que los using namespace
en los encabezados escapen de los ámbitos de los encabezados, de manera que una cantidad arbitrariamente grande El código de cliente directo e indirecto no puede tomar sus propias decisiones sobre qué espacios de nombres usar y cómo manejar las ambigüedades.
Por lo tanto, un líder ::
es una herramienta en la caja de herramientas del programador de C ++ para desambiguar activamente un choque conocido, y / o eliminar la posibilidad de ambigüedad futura ...
su operador de resolución de alcance llamado, Se puede hacer referencia a un nombre global oculto utilizando el operador de resolución de alcance:
Por ejemplo;
int x;
void f2()
{
int x = 1; // hide global x
::x = 2; // assign to global x
x = 2; // assign to local x
// ...
}
::
es el operador de resolución de alcance. Se utiliza para especificar el alcance de algo.
Por ejemplo, ::
alone es el ámbito global, fuera de todos los demás espacios de nombres.
some::thing
puede interpretarse de cualquiera de las siguientes maneras:
-
some
es un espacio de nombres (en el ámbito global, o un ámbito externo al actual) ything
es un tipo , una función , un objeto o un espacio de nombres anidado ; -
some
es una clase disponible en el alcance actual ything
es un objeto miembro , función o tipo desome
clase; - en una función miembro de clase ,
some
pueden ser un tipo base del tipo actual (o el tipo actual en sí mismo) ything
es entonces 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, bad
, también podría ser una función. Los otros no pudieron, ya que las funciones no pueden exponer nada dentro de su alcance interno.
Entonces, volviendo a su ejemplo, ::thing
puede ser solo algo en el ámbito global: un tipo, una función, un objeto o un espacio de nombres.
La forma en que lo usa sugiere (utilizado 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.
::
es un operador de definir el espacio de nombres.
Por ejemplo, si desea usar cout sin mencionar el using namespace std;
en tu código escribes esto:
std::cout << "test";
Cuando no se menciona ningún espacio de nombres, se dice que la clase pertenece al espacio de nombres global.
::
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 de ::
, entonces subraya el hecho de que está utilizando el espacio de nombres global.
p.ej:
::doMyGlobalFunction();