Class declaration
Les classes sont des types définis par l'utilisateur, définis par un spécificateur de classe, qui apparaît dans la decl-specifier-seq de la déclaration syntaxe.
Table des matières |
Syntaxe
Le spécificateur de classe a la syntaxe suivante :
class-key
attr
(optionnel)
class-head-name
class-property-specs
(optionnel)
base-clause
(optionnel)
{
member-specification
}
|
(1) | ||||||||
class-key
attr
(optionnel)
base-clause
(optionnel)
{
member-specification
}
|
(2) | ||||||||
| class-key | - | l'un des mots-clés class , struct et union . Les mots-clés class et struct sont identiques sauf pour l' accès aux membres par défaut et l' accès à la classe de base par défaut. S'il s'agit de union , la déclaration introduit un type union . | ||||||||
| attr | - |
(depuis C++11)
n'importe quel nombre d'
attributs
, peut inclure le spécificateur
alignas
|
||||||||
| class-head-name | - | le nom de la classe qui est définie, optionnellement qualifié | ||||||||
| class-property-specs | - |
Une liste des spécificateurs suivants, chaque spécificateur est autorisé au plus une fois dans chaque séquence.
|
||||||||
| base-clause | - | liste d'une ou plusieurs classes de base et le modèle d'héritage utilisé pour chacune (voir classe dérivée ) | ||||||||
| member-specification | - | liste des spécificateurs d'accès, des déclarations et définitions d'objets membres et de fonctions membres ( voir ci-dessous ) |
Déclaration anticipée
Une déclaration de la forme suivante
class-key
attr
identifier
;
|
|||||||||
Déclare un type de classe qui sera défini ultérieurement dans cette portée. Jusqu'à ce que la définition apparaisse, ce nom de classe a un type incomplet . Cela permet à des classes qui se référencent mutuellement :
class Vector; // déclaration anticipée class Matrix { // ... friend Vector operator*(const Matrix&, const Vector&); }; class Vector { // ... friend Vector operator*(const Matrix&, const Vector&); };
et si un fichier source particulier n'utilise que des pointeurs et des références vers la classe, cela permet de réduire #include les dépendances :
// Dans MyStruct.h #include <iosfwd> // contient la déclaration anticipée de std::ostream struct MyStruct { int value; friend std::ostream& operator<<(std::ostream& os, const S& s); // définition fournie dans le fichier MyStruct.cpp qui utilise #include <ostream> };
Si une déclaration anticipée apparaît dans une portée locale, elle masque la classe, variable, fonction précédemment déclarée, et toutes les autres déclarations du même nom pouvant apparaître dans les portées englobantes :
struct s { int a; }; struct s; // ne fait rien (s est déjà défini dans cette portée) void g() { struct s; // déclaration anticipée d'une nouvelle structure locale "s" // cela masque la structure globale s jusqu'à la fin de ce bloc s* p; // pointeur vers la structure locale s struct s { char* p; }; // définition de la structure locale s }
Notez qu'un nouveau nom de classe peut également être introduit par un elaborated type specifier qui apparaît comme partie d'une autre déclaration, mais seulement si name lookup ne peut pas trouver une classe précédemment déclarée avec le même nom.
class U; namespace ns { class Y f(class T p); // déclare la fonction ns::f et déclare ns::T et ns::Y class U f(); // U fait référence à ::U // peut utiliser des pointeurs et références vers T et Y Y* p; T* q; }
Spécification des membres
La spécification des membres, ou le corps d'une définition de classe, est une séquence entre accolades d'un nombre quelconque des éléments suivants :
attr
(optionnel)
decl-specifier-seq
(optionnel)
member-declarator-list
(optionnel)
;
|
|||||||||
| attr | - | (depuis C++11) n'importe quel nombre d' attributs |
| decl-specifier-seq | - | séquence de spécificateurs . Elle n'est optionnelle que dans les déclarations des constructeurs, destructeurs et fonctions de conversion de type définies par l'utilisateur |
| member-declarator-list | - |
similaire à une
init-declarator-list
, mais permet en plus la
déclaration de champ de bits
, la
pure-specifier
, et le virt-specifier (
override
ou
final
)
(depuis C++11)
, et n'autorise pas la
syntaxe de direct-non-list-initialization
.
|
Cette déclaration peut déclarer des données membres statiques et non statiques, des fonctions membres , des typedefs membres , des énumérations membres et des classes imbriquées . Elle peut également être une déclaration friend .
class S { int d1; // non-static data member int a[10] = {1, 2}; // non-static data member with initializer (C++11) static const int d2 = 1; // static data member with initializer virtual void f1(int) = 0; // pure virtual member function std::string d3, *d4, f2(int); // two data members and a member function enum { NORTH, SOUTH, EAST, WEST }; struct NestedS { std::string s; } d5, *d6; typedef NestedS 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) {} // constructor definition int operator()(std::size_t r, std::size_t c) const // member function definition { return data[r * C + c]; } int& operator()(std::size_t r, std::size_t c) // another member function definition { return data[r * C + c]; } };
public:
,
protected:
, et
private:
class S { public: S(); // constructeur public S(const S&); // constructeur de copie public virtual ~S(); // destructeur virtuel public private: int* ptr; // membre de données privé };
class Base { protected: int d; }; class Derived : public Base { public: using Base::d; // rendre le membre protégé d de Base un membre public de Derived using Base::Base; // hériter de tous les constructeurs des classes de base (C++11) };
static_assert
déclarations :
template<typename T> struct Foo { static_assert(std::is_floating_point<T>::value, "Foo<T>: T must be floating point"); };
struct S { template<typename T> void f(T&& n); template<class CharT> struct NestedS { std::basic_string<CharT> s; }; };
| (depuis C++11) |
|
8)
guides de déduction
des modèles de classe membres :
struct S { template<class CharT> struct NestedS { std::basic_string<CharT> s; }; template<class CharT> NestedS(std::basic_string<CharT>) -> NestedS<CharT>; }; |
(depuis C++17) |
|
9)
Déclarations using-enum
:
enum class color { red, orange, yellow }; struct highlight { using enum color; }; |
(depuis C++20) |
Classes locales
Une déclaration de classe peut apparaître dans le corps d'une fonction, auquel cas elle définit une classe locale . Le nom d'une telle classe n'existe que dans la portée de la fonction, et n'est pas accessible à l'extérieur.
- Les membres d'une classe locale ne peuvent être déclarés que dans la définition de cette classe, sauf que les membres qui sont des classes imbriquées peuvent également être déclarés dans la portée de bloc la plus proche englobant cette classe.
- Une classe imbriquée dans une classe locale est également une classe locale.
- Une classe locale ne peut pas avoir de membres de données statiques.
- Les fonctions membres d'une classe locale n'ont pas de liaison.
- Les fonctions membres d'une classe locale doivent être définies entièrement dans le corps de la classe.
- Les classes locales autres que les types de fermeture (depuis C++14) ne peuvent pas avoir de modèles membres.
- Les classes locales ne peuvent pas avoir de modèles amis .
- Les classes locales ne peuvent pas définir de fonctions amies dans la définition de la classe.
- Une classe locale à l'intérieur d'une fonction (y compris une fonction membre) peut accéder aux mêmes noms que la fonction englobante peut accéder.
|
(jusqu'à C++11) |
#include <algorithm> #include <iostream> #include <vector> 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()); // since C++11 for (int n : v) std::cout << n << ' '; std::cout << '\n'; }
Sortie :
3 2 1
Mots-clés
Rapports de défauts
Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.
| DR | Applicable à | Comportement publié | Comportement corrigé |
|---|---|---|---|
| CWG 1693 | C++98 | les déclarations de membres ne pouvaient pas être vides | déclaration vide autorisée |
| CWG 1930 | C++98 |
member-declarator-list
pouvait être vide lorsque
decl-specifier-seq
contient un spécificateur de classe de stockage ou un qualificatif cv |
la liste ne doit pas être vide |
| CWG 2890 | C++98 | il n'était pas clair où les membres des classes imbriquées pouvaient être déclarés | clarifié |
Voir aussi
|
Documentation C
pour
Déclaration de struct
|