Declaración de clase
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:
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; };
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]; } };
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 };
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) };
template<typename T> struct Foo { static_assert(std::is_floating_point<T>::value, "Foo<T>: T tiene que ser de punto flotante"); };
struct S { template<typename T> void f(T&& n); template<class CharT> struct NestedS { std::basic_string<CharT> s; }; };
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.
|
(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
|