Espacios de nombres
Variantes
Acciones

Tipo

De cppreference.com
< cpp‎ | language

Los objetos, referencias, funciones (incluyendo funciones de plantilla especializadas), y expresiones tienen una propiedad denominada “tipo”, que restringe las operaciones que se pueden realizar con esas entidades, y les proporciona un significado semántico a a lo que de otra manera sería una secuencia genérica de bits.

Contenido

[editar] Clasificación de tipos

El sistema de tipos en C++ consiste en los siguientes tipos:

  • tipo lógico, bool;
  • tipos de carácter:
  • tipos simples de carácter (char, signed char, unsigned char);
  • tipos extendidos de carácter (char16_t, char32_t, wchar_t);
  • tipos enteros con signo (short int, int, long int, long long int);
  • tipos enteros sin signo (unsigned short int, unsigned int, unsigned long int, unsigned long long int);
  • tipos de referencia lvalue a objeto;
  • tipos de referencia lvalue a función;
  • tipos de referencia rvalue a objeto;
  • tipos de referencia rvalue a función;

Para cada tipo aparte de una referencia o función, el sistema de tipos admite además tres versiones calificadas-cv de dicho tipo: (const, volatile y const volatile).

Los tipos se agrupan en varias categorías según sus propiedades:

[editar] Denominación de tipos

Un nombre puede ser declarado para referirse a un tipo que significa:

A menudo, en programas de C++, se necesita usar tipos que no tienen nombre; la sintaxis para esto se conoce como id de tipo. La sintaxis del id de tipo que nombra al tipo T es exactamente la sintaxis de una declaración de una variable o función de tipo T, omitiendo el identificador, excepto que la secuencia de declaración de especificaciones de la gramática de declaración está restringida a una secuencia específica de tipo, y que los nuevos tipos pueden definirse solo si el id de tipo aparece en el lado derecho de una declaración de un alias que no sea de plantilla.

int* p;               // declaración de puntero a entero
static_cast<int*>(p); // el id de tipo es "int*"
 
int a[3];   // declaración de un vector de 3 enteros
new int[3]; // id de tipo es "int[3]" (denominado new-type-id)
 
int (*(*x[2])())[3];      // declaración de un vector de 2 punteros a función
                          // devuelve un puntero a un vector de 3 enteros
new (int (*(*[2])())[3]); // id de tipo es "int (*(*[2])())[3]"
 
void f(int);                    // declaración de una función con un entero de parámetro 
                                //y que no devuelve un valor (void).
std::function<void(int)> x = f; // el tipo del parámetro de la plantilla (template) es 
                                //id de tipo "void(int)"
std::function<auto(int) -> void> y = f; // igual
 
std::vector<int> v;       // declaración de un vector de enteros
sizeof(std::vector<int>); // id de tipo es "std::vector<int>"
 
struct { int x; } b;         // se crea nuevo tipo y se declara un objeto b de ese tipo
sizeof(struct{ int x; });    // error: no se puede definir nuevos tipos en expresión sizeof
using t = struct { int x; }; // se crea nuevo tipo y se declara t como un alias de ese tipo
 
sizeof(static int); // error: los especificadores de tipo de almacenamiento no son parte 
                    //de la secuencia específica de tipo 
std::function<inline void(int)> f; // error: tampoco son específica de función

La parte de “declaración” de la gramática donde no se especifica el nombre se conoce como “declaración abstracta”.

Id de tipo se puede utilizar en la siguientes situaciones:


El “id de tipo” se puede usar con algunos modificadores en los siguientes casos:

  • en la lista de parámetros de una función (cuando se omite el nombre del parámetro), id de tipo usa una secuencia de especificaciones de declaración en vez de una secuencia de especificaciones de tipo (en particular, algunos especificadores de almacenamiento se permiten);
  • en el nombre de una función de conversión definida por usuario, la declaración abstracta no puede incluir operadores de matriz o función.

[editar] Especificador de tipo elaborado

Los especificadores de tipo elaborados se pueden usar para referirse a un nombre de clase (class, struct o union) declarado previamente, o a un nombre de enumerador declarado previamente, incluso si el nombre estaba oculto por una declaración sin tipo. También pueden usarse para declarar nuevos nombres de clase.

Véase especificador de tipo elaborado para más detalles.

[editar] Tipo estático

El tipo de una expresión se denomina como tipo estático si es el resultado del análisis en tiempo de compilación del programa. El tipo estático no cambia durante la ejecución del programa.

[editar] Tipo dinámico

Si alguna expresión glvalue se refiere a un objeto polimórfico, el tipo de su objeto más derivado se conoce como el tipo dinámico.

struct B { virtual ~B() {} }; // tipo polimórfico 
struct D: B {}; // tipo polimórfico
D d; // objeto derivado
B* ptr = &d;
// el tipo estático de (*ptr) es B
// el tipo dinámico de (*ptr) es D

Para las expresiones prvalue, el tipo dinámico siempre es el mismo que el estático.

[editar] Tipo incompleto

Los siguientes son tipos incompletos:

En cualquiera de la siguientes situaciones se requiere que la clase T sea completa:

(En general, cuando se debe conocer el tamaño y formato de T).

Si alguna de estas situaciones se da en una unidad de traducción, la definición del tipo debe aparecer en la misma. En otro caso, no es obligatorio.

[editar] Véase también