Espacios de nombres
Variantes
Acciones

Declaración de clase

De cppreference.com
< cpp‎ | language
 
 
 
 

Las clases y estructuras son tipos definidos por el usuario, definidos mediante el especificador de clase, que aparece en la sec-decl-especificadores de la sintaxis de declaración. El especificador de clase tiene la siguiente sintaxis:

clave-de-clase atrib nombre-de-la-clase cláusula-de-base { especificación-de-miembro }
clave-de-clase - Uno de class o struct. Las palabras claves son idénticas excepto por el accesso a miembros por defecto y el acceso a la clase base por defecto.
atrib(C++11) - Secuencia opcional de cualquier número de atributos, puede incluir el especificador alignas.
nombre-de-la-clase - El nombre de la clase que se define. Opcionalmente calificada, opcionalmente seguido de la palabra clave final. El nombre puede omitirse, en cuyo caso la clase no tiene nombre (observa que una clase sin nombre no puede ser final).
cláusula-de-base - Lista opcional de una o más clases base y el modelo de herencia utilizado para cada una (véase clases derivadas)
especificación-de-miembro - Lista de especificadores de acceso, declaraciones y definiciones de objetos miembro y funciones miembro (véase abajo).

Véase clases para una visión general de la sintaxis. Si la clave-de-clase es union, la declaración introduce un tipo unión.

Contenido

[editar] Declaración adelantada

Una declaración de la siguiente forma

clave-de-clase atrib identificador ;

Declara un tipo clase que se definirá más adelante en este ámbito. Hasta que aparezca la definición, este nombre de clase tiene un tipo incompleto. Esto permite que las clases se refieran entre sí:

class Vector; // declaración adelantada
class Matrix {
    // ...
    friend Vector operator*(const Matrix&, const Vector&);
};
class Vector {
    // ...
    friend Vector operator*(const Matrix&, const Vector&);
};

y si un archivo fuente en particular solo usa punteros y referencias a la clase, esto hace posible reducir las dependencias #include:

// en MiEstructura.h 
#include <iosfwd> // contiene declaraciones adelantadas de std::ostream
struct MiEstructura {
    int value;
    friend std::ostream& operator<<(std::ostream& os, const S& s);
    // la definición proporcionada en MiEstructura.cpp file que usa #include <ostream>
};

Si la declaración adelantada aparece en el ámbito local, oculta la clase, la variable, la función y todas las demás declaraciones del mismo nombre previamente declaradas que pueden aparecer en los ámbitos adjuntos:

struct s { int a; };
struct s; // no hace nada (s ya está definida en este ámbito)
void g() {
    struct s; // declaración adelantada de una estructura s nueva, local
              // esto oculta la estructura global shasta el final de este bloque
    s* p;     // puntero a la estructura local s;
    struct s { char* p; }; // definiciones de la estructura local s
}

Observa que un nuevo nombre de clase también puede ser introducido por un especificador de tipo elaborado que aparece como parte de otra declaración, pero solo si la búsqueda de nombre no puede encontrar una clase previamente declarada con el mismo nombre.

class U;
namespace ns{
    class Y f(class T p); // declara la función ns::f y declara a ns::T y ns::Y
    class U f(); // U se refiere a ::U
    Y* p; T* q; // puede usar punteros y referencias a T e Y
}

[editar] Especificación de miembros

La especificación de miembros, o el cuerpo de una definición de clase es una secuencia entre llaves de cualquier número de los siguientes:

1) Declaraciones de miembros de la forma
atrib(opcional) sec-decl-especificadores(opcional) lista-decl-miembros(opcional) ;
atrib(C++11) - Secuencia opcional de cualquier número de atributos
sec-decl-especificadores - Secuencia de especificadores. Es opcional solamente en las declaraciones de constructores, destructores y tipos función de conversión definidos por el usuario.
lista-decl-miembros - Similar a una lista-decl-inicializadores, pero permite además declaraciones de campos de bits, el especificador puro, y el especificador virtual (override o final) (desde C++11), y no permite la sintaxis de inicialización directa que no usa lista.

Esta declaración puede declarar data members estáticos y no estáticos, y funciones miembro, definiciones de tipo miembro, enumeraciones miembro, y clases anidadas. También puede ser una declaración friend.

class S {
    int d1; // dato miembro no estático
    int a[10] = {1,2}; // dato miembro no estático con inicializador (C++11)
    static const int d2 = 1; // dato miembro estático con inicializador
    virtual void f1(int) = 0; // función miembro virtual pura
    std::string d3, *d4, f2(int); // dos datos miembro y una función miembro
    enum {NORTE, SUR, ESTE, OESTE};
    struct SAnidada {
        std::string s;
    } d5, *d6;
    typedef SAnidada value_type, *pointer_type;
};
2) Definiciones de funciones, que declaran y definen funciones miembro o funciones amigas. Un punto y coma después de una definición de función miembro es opcional. Todas las funciones que se definen dentro de un cuerpo de clase son automáticamente inline.
class M {
    std::size_t C;
    std::vector<int> data;
 public:
    M(std::size_t R, std::size_t C) : C(C), data(R*C) {} // definición de constructor 
    int operator()(size_t r, size_t c) const { // definición de función miembro
        return data[r*C+c];
    }
    int& operator()(size_t r, size_t c) {  // otra definición de función miembro
        return data[r*C+c];
    }
};
3) Especificadores de acceso public:, protected:, y private:
class S {
 public:
    S();          // constructor público
    S(const S&);  // constructor de copia público
    virtual ~S(); // destructor virtual público
 private:
    int* ptr; // private data member
};
4) Declaraciones using
class Base {
 protected:
     int d;
};
class Derivada : public Base {
 public:
    using Base::d; // hace al miembro protegido de de Base un miembro público de Derivada
    using Base::Base; // hereda todos los constructores de la clase base (C++11)
};
5) Declaraciones static_assert
template<typename T>
struct Foo {
  static_assert(std::is_floating_point<T>::value, "Foo<T>: T tiene que ser de punto flotante");
};
6) Declaraciones de plantillas de miembro de clase
struct S {
    template<typename T>
    void f(T&& n);
 
    template<class CharT>
    struct NestedS {
        std::basic_string<CharT> s;
    };
};
7) Declaraciones de alias
template <typename T>
struct identity
{
    using type = T;
};
8) Guías de deducción de plantillas de miembro de clase:
struct S {
    template<class CharT>
    struct SAnidada {
        std::basic_string<CharT> s;
    };
 
    template<class CharT>
    SAnidada(std::basic_string<CharT>) -> SAnidada<CharT>;
};
(desde C++17)

[editar] Clases locales

Una declaración de clase puede aparecer en el ámbito del espacio de nombres (en cuyo caso define una clase ordinaria), dentro de otra definición de clase (en cuyo caso define una clase anidada), y dentro del cuerpo de una función, en cuyo caso define una "clase local". El nombre de dicha clase solo existe dentro del ámbito de la función y no es accesible desde afuera.

  • Una clase local no puede tener datos miembro estáticos.
  • Las funciones miembro de una clase local no tienen enlace.
  • Las funciones miembro de una clase local deben definirse completamente dentro del cuerpo de la clase.
  • Las clases locales que no sean tipos cierre (desde C++14) no pueden tener plantillas de miembros de clase.
  • Las clases locales no pueden tener plantillas amigas.
  • Las clases locales no pueden definir funciones amigas dentro de la definición de clase.
  • Una clase local dentro de una función (incluida una función miembro) puede acceder a los mismos nombres a los que puede acceder la función que la contiene.
  • Las clases locales no podían ser usadas como argumentos de plantilla
(hasta C++11)
#include <vector>
#include <algorithm>
#include <iostream>
 
int main()
{
    std::vector<int> v{1,2,3};
    struct Local {
       bool operator()(int n, int m) {
           return n > m;
       }
    };
    std::sort(v.begin(), v.end(), Local()); // desde C++11
    for(int n: v) std::cout << n << ' ';
}

Salida:

3 2 1

[editar] Véase también

Documentación de C para Declaración de estructuras