El operador cuatro puntos (::
) es el operador de jerarquía en c++1 y nos indica que el símbolo de la derecha, está subordinado jerárquicamente al símbolo de la izquierda:
A :: B; // B está contenido en A.
Las relaciones jerárquicas que puedes tener son a nivel de objeto, enumerado o espacio de nombres:
namespace Espacio_de_nombres
{
struct Objeto
{
enum class Enumerado
{
Elemento
};
int entero;
static float flotante;
};
Objeto instancia;
using Entero = int;
}
Por lo tanto:
// Un enumerado anidado en un objeto anidado en un espacio de nombres
std::cout << (int)Espacio_de_nombres::Objeto::Enumerado::Elemento;
// Un valor dentro de una instancia anidada en un espacio de nombres
std::cout << Espacio_de_nombres::instancia.entero;
// Un valor estático dentro de un objeto anidado en un espacio de nombres
std::cout << Espacio_de_nombres::Objeto::flotante;
// Un objeto anidado en un espacio de nombres
std::cout << &Espacio_de_nombres::instancia;
// Un alias anidado en un espacio de nombres.
Espacio_de_nombres::Entero x;
Ahora respondamos a las preguntas:
¿Por qué cuando desarrollamos una clase se utilizan los ::
ej: MiClase::Funcion(){}
?
Porque Funcion()
pertenece al objeto MiClase
, si usas la función Funcion()
fuera del ámbito del objeto necesitarás el nombre completo, mientras que dentro del objeto no es necesario:
// Declaración
struct MiClase
{
int Funcion();
int Otra_Funcion();
}
// Definición
int MiClase::Funcion()
// ^^ <--- Necesitamos decir que 'Funcion' pertenece a 'MiClase'
{
return Otra_Funcion();
// ~~~~~~~~~~~~ <--- Estamos dentro de 'MiClase', no necesitamos el nombre completo
}
int MiClase::Otra_Funcion()
// ^^ <--- Necesitamos decir que 'Otra_Funcion' pertenece a 'MiClase'
{
return 42;
}
¿Y cuando utilizamos una funcion de la libreria estandar de c++ tambien usamos ::
pero para hacer uso de la función?
Cuando te refieres a un objeto dentro del espacio de nombres estándar (std
es standard) es necesario el nombre completo a no ser que digas que en un ámbito concreto vas a asumir el uso de dicho espacio de nombres:
std::string cadena = "Hola Mundo";
// ^^~~~~ <--- El tipo 'string' está dentro del espacio de nombres 'std'
std::cout << cadena;
// ^^~~~~ <--- El objeto 'cout' está dentro del espacio de nombres 'std'
auto a = std::toupper('a');
// ^^~~~~~~~~ <--- La función 'toupper' está dentro del espacio de nombres 'std'
Si hubieses usado la cláusula using namespace std
no te habría hecho falta escribir el nombre completo, lee este hilo para saber más.
¿Por qué algunas librerías como cstdlib no necesitan std:: para funcionar?
La cabecera (que no librería) cstdlib
es la cabecera stdlib.h
de C adaptada al lenguaje C++. No pertenecen a la librería estándar de C++ y por ello podrían2 no estar incluidas en el espacio de nombres estándar. Lee este hilo para saber más.
1Es uno de los pocos operadores que no puede ser sobrecargado.
2En general, las cabeceras estándar tienen "permitido" publicar símbolos en el espacio de nombres global, pero en la práctica se suele evitar.