Namespaces
Variants

Class declaration

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Class/struct types
Union types

Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

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)
1) Définition de classe nommée
2) Définition de classe anonyme
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.
Spécificateur Effet
final
(depuis C++11)
Spécifie que la classe ne peut pas être dérivée
trivially_relocatable_if_eligible
(depuis C++26)
Marque la classe comme étant trivialement relogeable si éligible
replaceable_if_eligible
(depuis C++26)
Marque la classe comme étant remplaçable si éligible
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 :

1) Les déclarations de membres de la forme
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;
};
2) Définitions de fonctions, qui déclarent et définissent à la fois les fonctions membres ou les fonctions amies . Un point-virgule après une définition de fonction membre est optionnel. Toutes les fonctions définies dans le corps d'une classe sont automatiquement inline , sauf si elles sont attachées à un module nommé (depuis C++20) .
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];
    }
};
3) Spécificateurs d'accès 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é
};
4) Déclarations using :
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)
};
5) static_assert déclarations :
template<typename T>
struct Foo
{
    static_assert(std::is_floating_point<T>::value, "Foo<T>: T must be floating point");
};
6) déclarations de modèles membres :
struct S
{
    template<typename T>
    void f(T&& n);
    template<class CharT>
    struct NestedS
    {
        std::basic_string<CharT> s;
    };
};
7) déclarations d'alias :
template<typename T>
struct identity
{
    using type = T;
};
(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.
  • Les classes locales ne pouvaient pas être utilisées comme arguments de template.
(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

class , struct , union

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