</>waridocu

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++.

cppsintaxisreferenciarepasofundamentos

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: ()

UsoSe ve asíDónde se explicó
Llamar a una funciónareaRectangulo(3.0, 4.5)Qué es una función
Declarar los parámetros de una funcióndouble 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.0Operadores básicos
Encerrar la condición de if, while, switchif (nota >= 4.0)Tomar decisiones con if
Encerrar las tres partes de un forfor (int i = 0; i < 5; ++i)El bucle for
Conversión explícita y sizeofstatic_cast<double>(suma), sizeof(notas)Aritméticos, Arrays y funciones
Desreferenciar antes de acceder a un miembro(*ptr).nombrePunteros a struct
Direct-init: construir con argumentosContador c(0);Direct-init
Llamar a un constructorCuentaBancaria 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.

Advertencia

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

UsoSe ve asíDónde se explicó
Delimitar un bloque y su ámbitoif (x > 0) { ... }Bloques y ámbito
El cuerpo de una funcióndouble area(...) { return ancho * alto; }Qué es una función
El cuerpo de un structstruct Persona { ... };Qué es un struct
El cuerpo de una claseclass CuentaBancaria { ... };Qué es una clase
List-init de una variabledouble altura{1.75};List-init
Value-init: el “valor cero” del tipoint x{};Value-init
Inicializar un arrayint notas[5] = {7, 4, 6, 3, 5};Qué es un array
Inicializar un struct miembro a miembroPunto 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.

Advertencia

Las llaves de un bloque no llevan ; al cerrar; las de un struct o clase sí: } frente a };. La razón es que la definición de un tipo es una declaración, y en C++ toda declaración termina en punto y coma. Es el olvido más habitual al escribir la primera clase, ya señalado en Structs y en Clases.

Los corchetes: []

UsoSe ve asíDónde se explicó
Declarar el tamaño de un arrayint notas[5];Qué es un array
Indexar: acceder a un elementonotas[0], notas[2] = 10;Recorrer un array
Indexar a través de un punterop[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.

Nota

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.

Nota

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

UsoSe ve asíDónde se explicó
Etiqueta case o default en un switchcase 1:Elegir entre muchas opciones con switch
Separador del for basado en rangofor (int nota : notas)El for basado en rango
Etiqueta de acceso en una clasepublic:, private:Encapsulación
Abrir la lista de inicialización de un constructorPersona(...) : 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ímboloNombreSignificado
:Dos puntosIntroduce 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”.

Tip

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.

Nota

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.

Ejemplo: los cuatro símbolos en un solo programacpp
#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;
}
bashbash
g++ -std=c++17 -Wall -o simbolos simbolos.cpp
./simbolos
texttext
Ana sumó los tres valores
primer valor: 10

Si 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.