C++
Repaso de sintaxis: (), {}, [] y :
Referencia rápida de todos los significados que tienen los paréntesis, las llaves, los corchetes y los dos puntos en C++.
Cómo usar esta página
Esta página no enseña nada nuevo. Es una referencia de consulta: recoge todos los usos de (), {}, [] y : que fueron apareciendo a lo largo de Fundamentos, cada uno en su propio contexto y a veces con varias páginas de distancia entre sí.
Está pensada para el momento en que estás leyendo código ajeno, ves un símbolo y te preguntas “¿qué significa aquí?”. Cada fila de cada tabla enlaza a la página donde ese uso se explicó de verdad, así que si una respuesta corta no te alcanza, el desarrollo completo está a un clic.
La razón de que haga falta una página así es una característica del lenguaje que ya se hizo notar dos veces: C++ reutiliza sus símbolos. Ya viste que * y & significan cosas distintas según estén en una declaración o en una expresión, y que :: y : no son el mismo símbolo aunque se parezcan. Lo que sigue es el mapa completo de los cuatro delimitadores más frecuentes.
Los paréntesis: ()
| Uso | Se ve así | Dónde se explicó |
|---|---|---|
| Llamar a una función | areaRectangulo(3.0, 4.5) | Qué es una función |
| Declarar los parámetros de una función | double area(double ancho, double alto) | Qué es una función |
| Prototipo (declarar sin definir) | double area(double, double); | Declaración y definición |
| Agrupar una expresión y forzar el orden | (nota1 + nota2) / 2.0 | Operadores básicos |
Encerrar la condición de if, while, switch | if (nota >= 4.0) | Tomar decisiones con if |
Encerrar las tres partes de un for | for (int i = 0; i < 5; ++i) | El bucle for |
Conversión explícita y sizeof | static_cast<double>(suma), sizeof(notas) | Aritméticos, Arrays y funciones |
| Desreferenciar antes de acceder a un miembro | (*ptr).nombre | Punteros a struct |
| Direct-init: construir con argumentos | Contador c(0); | Direct-init |
| Llamar a un constructor | CuentaBancaria cuenta("Ana", 1000.0); | Constructores |
Los dos últimos son el mismo uso visto desde dos lados: para el compilador, Contador c(0); es “inicialización directa de c”, y esa inicialización consiste en llamar al constructor de Contador.
El caso que rompe la intuición son los paréntesis vacíos en una declaración: Widget c(); no construye un objeto, declara una función. Es el most vexing parse, y está explicado con su ejemplo completo en la página anterior. La forma segura de decir “constrúyelo con el constructor por defecto” es Widget c; o Widget c{};.
Las llaves: {}
| Uso | Se ve así | Dónde se explicó |
|---|---|---|
| Delimitar un bloque y su ámbito | if (x > 0) { ... } | Bloques y ámbito |
| El cuerpo de una función | double area(...) { return ancho * alto; } | Qué es una función |
| El cuerpo de un struct | struct Persona { ... }; | Qué es un struct |
| El cuerpo de una clase | class CuentaBancaria { ... }; | Qué es una clase |
| List-init de una variable | double altura{1.75}; | List-init |
| Value-init: el “valor cero” del tipo | int x{}; | Value-init |
| Inicializar un array | int notas[5] = {7, 4, 6, 3, 5}; | Qué es un array |
| Inicializar un struct miembro a miembro | Punto p{3.0, 4.0}; | Inicialización de agregados |
La división es más simple de lo que sugiere la tabla: unas llaves delimitan código que se ejecuta (las cuatro primeras filas) o encierran valores (las cuatro últimas). Si dentro hay sentencias, es un bloque; si dentro hay una lista de valores separados por comas, es una inicialización.
Los corchetes: []
| Uso | Se ve así | Dónde se explicó |
|---|---|---|
| Declarar el tamaño de un array | int notas[5]; | Qué es un array |
| Indexar: acceder a un elemento | notas[0], notas[2] = 10; | Recorrer un array |
| Indexar a través de un puntero | p[2], equivalente a *(p + 2) | La relación entre arrays y punteros |
Es el símbolo con menos significados de los cuatro, y los tres son la misma idea vista desde ángulos distintos: elegir una posición dentro de una secuencia contigua de memoria.
Los contenedores de la Standard Library, como std::vector, también se indexan con [] y con la misma semántica (v[0] es el primer elemento). La diferencia es que ahí [] no es sintaxis del lenguaje sino un operador sobrecargado que la clase define, la misma técnica que hace que << funcione con std::cout. Eso se retoma en la sección Standard Library de esta documentación.
También verás [] al principio de una lambda ([](int a, int b) { return a + b; }), donde no indexa nada: es la lista de captura de una función anónima. Las lambdas son C++ moderno y no forman parte de Fundamentos; se nombran aquí solo para que reconozcas que ese [] es otra cosa y no lo interpretes como un array.
Los dos puntos: :
| Uso | Se ve así | Dónde se explicó |
|---|---|---|
Etiqueta case o default en un switch | case 1: | Elegir entre muchas opciones con switch |
Separador del for basado en rango | for (int nota : notas) | El for basado en rango |
| Etiqueta de acceso en una clase | public:, private: | Encapsulación |
| Abrir la lista de inicialización de un constructor | Persona(...) : nombre_(n) {} | La lista de inicialización de miembros |
Los cuatro usos comparten un aire de familia que ayuda a recordarlos: el : siempre introduce lo que viene después. En un case, el código que se ejecuta para ese valor; en un for de rango, el contenedor que se recorre; en public:, los miembros que serán públicos; en un constructor, los valores con los que nacen los miembros.
Dos puntos simples y dobles no son lo mismo
: y :: se parecen a simple vista pero no tienen ninguna relación. :: es el operador de resolución de ámbito, y significa siempre lo mismo: “lo que sigue vive dentro de lo que precede”.
| Símbolo | Nombre | Significado |
|---|---|---|
: | Dos puntos | Introduce algo, según los cuatro contextos de la tabla anterior |
:: | Resolución de ámbito | “Dentro de”: namespace, clase o enumeración |
Sus dos usos ya aparecieron: en std::cout significa “el cout que vive dentro del namespace std”, y en Contador::incrementar significa “el incrementar que pertenece a la clase Contador”.
Si el compilador te lanza un error tan poco informativo como expected unqualified-id o expected ';' before ':' token en una línea que se ve bien, cuenta los dos puntos. Escribir std:cout en vez de std::cout, o Contador:incrementar en vez de Contador::incrementar, produce exactamente ese tipo de mensaje desorientador.
Hay un quinto uso de : que no se cubrió en Fundamentos: el operador condicional ternario (condicion ? valorA : valorB), una forma compacta de escribir un if/else que devuelve un valor. Se menciona aquí solo para que no te sorprenda al encontrarlo en código ajeno.
Los cuatro símbolos en un solo programa
Este programa no hace nada útil: existe para que veas los cuatro delimitadores conviviendo, cada uno en un uso distinto, en menos de cuarenta líneas.
#include <iostream>
#include <string>
class Jugador { // {} delimitan el cuerpo de la clase
public: // : cierra la etiqueta de acceso
Jugador(const std::string& nombre) // () encierran los parámetros
: nombre_(nombre), puntos_(0) {} // : abre la lista de inicialización
void sumar(int p) { puntos_ += p; } // {} delimitan el cuerpo del método
int puntos() const { return puntos_; }
const std::string& nombre() const { return nombre_; }
private:
std::string nombre_;
int puntos_;
}; // ; obligatorio al cerrar la clase
int main() {
int tabla[3] = {10, 20, 30}; // [] fija el tamaño, {} inicializa el agregado
Jugador ana{"Ana"}; // {} list-init de un objeto
for (int p : tabla) { // : separa la variable del contenedor
ana.sumar(p); // () llaman a la función
}
switch (ana.puntos()) { // () obligatorios de switch
case 60: // : cierra la etiqueta del case
std::cout << ana.nombre() << " sumó los tres valores\n";
break;
default:
std::cout << "total inesperado: " << ana.puntos() << "\n";
break;
}
std::cout << "primer valor: " << tabla[0] << "\n"; // [] indexa
return 0;
}g++ -std=c++17 -Wall -o simbolos simbolos.cpp
./simbolosAna sumó los tres valores
primer valor: 10Si puedes leer ese programa y decir en voz alta qué hace cada símbolo en cada línea, Fundamentos cumplió su trabajo.
Hasta acá llega Fundamentos
Este es el final de la sección. Repasando el camino: empezaste por qué es C++ y cómo se compila, seguiste con variables, control de flujo y funciones, bajaste al nivel de la memoria con arrays y punteros, y volviste a subir para construir tus propios tipos con structs y clases.
Con eso ya puedes leer y escribir programas completos en C++, y —más importante— entender por qué el lenguaje se comporta como se comporta en vez de memorizar recetas.
La documentación continúa por dos caminos que puedes recorrer en el orden que prefieras: la Standard Library, que reemplaza buena parte de la maquinaria manual de esta sección por herramientas que se encargan solas (std::vector en lugar de arrays de tamaño fijo, std::string en lugar de cadenas terminadas en cero), y Dear ImGui, una librería para construir interfaces gráficas donde vas a reconocer casi todo lo que aprendiste aquí funcionando en un proyecto real. Ambas están en la barra lateral.