Recherche…


Introduction

Les mots-clés ont une signification fixe définie par le standard C ++ et ne peuvent pas être utilisés comme identificateurs. Il est illégal de redéfinir les mots clés en utilisant le préprocesseur dans une unité de traduction incluant un en-tête de bibliothèque standard. Cependant, les mots-clés perdent leur signification particulière dans les attributs.

Syntaxe

  • asm ( string-literal );
  • noexcept ( expression ) // sens 1
  • noexcept ( expression constante ) // sens 2
  • noexcept // sens 2
  • sizeof expression unaire
  • sizeof ( id-type )
  • sizeof ... ( identifiant ) // depuis C ++ 11
  • typename identifiant -nom-spécificateur identificateur // signification 1
  • modèle de spécificateur de nom imbriqué- typename ( opt ) simple-template-id // sens 1
  • identifiant typename ( opt ) // sens 2
  • typename ... identifiant ( opt ) // signifiant 2; depuis C ++ 11
  • identifiant typename ( opt ) = id-type // signifiant 2
  • template < template-liste-paramètres > typename ... ( opt ) identifiant ( opt ) // signification 3
  • template < template-liste-paramètres > identifiant typename ( opt ) = id-expression // signifiant 3

Remarques

La liste complète des mots-clés est la suivante:

Les jetons final et le override ne sont pas des mots clés. Ils peuvent être utilisés comme identifiants et n'ont une signification particulière que dans certains contextes.

Les jetons and , and_eq , bitand , bitor , compl , not , not_eq or or_eq , xor et xor_eq sont des orthographes alternatives de && , &= , & , | , ~ ! , != , || , respectivement |= , ^ et ^= . La norme ne les traite pas comme des mots-clés, mais ils sont des mots-clés à toutes fins utiles, car il est impossible de les redéfinir ou de les utiliser autrement que par les opérateurs qu'ils représentent.

Les rubriques suivantes contiennent des explications détaillées sur de nombreux mots-clés en C ++, qui servent des objectifs fondamentaux tels que le nom des types de base ou le contrôle du flux d'exécution.

asm

Le mot clé asm prend un seul opérande, qui doit être un littéral de chaîne. Il a une signification définie par l'implémentation, mais est généralement transmise à l'assembleur de l'implémentation, la sortie de l'assembleur étant incorporée dans l'unité de traduction.

L'instruction asm est une définition et non une expression . Elle peut donc apparaître soit dans la portée du bloc, soit dans la portée de l'espace de noms (y compris la portée globale). Cependant, comme l'assembly inline ne peut pas être contraint par les règles du langage C ++, asm peut ne pas apparaître dans une fonction constexpr .

Exemple:

[[noreturn]] void halt_system() {
    asm("hlt");
}

explicite

  1. Lorsqu'elle est appliquée à un constructeur à argument unique, empêche ce constructeur d'être utilisé pour effectuer des conversions implicites.

    class MyVector {
      public:
        explicit MyVector(uint64_t size);
    };
    MyVector v1(100);  // ok
    uint64_t len1 = 100;
    MyVector v2{len1}; // ok, len1 is uint64_t
    int len2 = 100;
    MyVector v3{len2}; // ill-formed, implicit conversion from int to uint64_t
    

    Étant donné que C ++ 11 a introduit des listes d'initialisation, en C ++ 11 et versions ultérieures, l' explicit peut être appliqué à un constructeur avec un nombre quelconque d'arguments, avec la même signification que dans le cas à argument unique.

    struct S {
        explicit S(int x, int y);
    };
    S f() {
        return {12, 34};  // ill-formed
        return S{12, 34}; // ok
    }
    
C ++ 11
  1. Appliqué à une fonction de conversion, cette fonction de conversion ne peut pas être utilisée pour effectuer des conversions implicites.

    class C {
        const int x;
      public:
        C(int x) : x(x) {}
        explicit operator int() { return x; }
    };
    C c(42);
    int x = c;                   // ill-formed
    int y = static_cast<int>(c); // ok; explicit conversion
    

pas d'exception

C ++ 11
  1. Opérateur unaire qui détermine si l'évaluation de son opérande peut propager une exception. Notez que les corps des fonctions appelées ne sont pas examinés, donc noexcept peut donner des faux négatifs. L'opérande n'est pas évalué.

    #include <iostream>
    #include <stdexcept>
    void foo() { throw std::runtime_error("oops"); }
    void bar() {}
    struct S {};
    int main() {
        std::cout << noexcept(foo()) << '\n'; // prints 0
        std::cout << noexcept(bar()) << '\n'; // prints 0
        std::cout << noexcept(1 + 1) << '\n'; // prints 1
        std::cout << noexcept(S()) << '\n';   // prints 1
    }
    

    Dans cet exemple, même si bar() ne peut jamais lancer une exception, noexcept(bar()) est toujours faux car le fait que bar() ne puisse pas propager une exception n'a pas été explicitement spécifié.

  2. Lors de la déclaration d'une fonction, spécifie si la fonction peut ou non propager une exception. Seul, il déclare que la fonction ne peut pas propager une exception. Avec un argument entre parenthèses, il déclare que la fonction peut ou ne peut pas propager une exception en fonction de la valeur de vérité de l'argument.

    void f1() { throw std::runtime_error("oops"); }
    void f2() noexcept(false) { throw std::runtime_error("oops"); }
    void f3() {}
    void f4() noexcept {}
    void f5() noexcept(true) {}
    void f6() noexcept {
        try {
            f1();
        } catch (const std::runtime_error&) {}
    }
    

    Dans cet exemple, nous avons déclaré que f4 , f5 et f6 ne peuvent pas propager des exceptions. (Bien qu'une exception puisse être levée lors de l'exécution de f6 , elle est interceptée et non autorisée à se propager hors de la fonction.) Nous avons déclaré que f2 peut propager une exception. Lorsque le spécificateur noexcept est omis, il est équivalent à noexcept(false) . Nous avons donc implicitement déclaré que f1 et f3 peuvent propager des exceptions, même si des exceptions ne peuvent pas être générées lors de l'exécution de f3 .

C ++ 17

Le fait que la fonction soit ou non ne fait noexcept partie du type de la fonction: dans l'exemple ci-dessus, f1 , f2 et f3 ont des types différents de f4 , f5 et f6 . Par conséquent, noexcept est également significatif dans les pointeurs de fonction, les arguments de modèle, etc.

void g1() {}
void g2() noexcept {}
void (*p1)() noexcept = &g1; // ill-formed, since g1 is not noexcept
void (*p2)() noexcept = &g2; // ok; types match
void (*p3)() = &g1;          // ok; types match
void (*p4)() = &g2;          // ok; implicit conversion

nom_type

  1. Lorsque suivi d'un nom qualifié, typename spécifie qu'il s'agit du nom d'un type. Cela est souvent requis dans les modèles, en particulier lorsque le spécificateur de nom imbriqué est un type dépendant autre que l'instanciation en cours. Dans cet exemple, std::decay<T> dépend du paramètre de modèle T , donc pour nommer le type de type imbriqué, il faut préfixer l'intégralité du nom qualifié avec typename . Pour plus de détails, voir Où et pourquoi dois-je mettre les mots-clés "template" et "typename"?

    template <class T>
    auto decay_copy(T&& r) -> typename std::decay<T>::type;
    
  2. Introduit un paramètre de type dans la déclaration d'un modèle . Dans ce contexte, il est interchangeable avec la class .

    template <typename T>
    const T& min(const T& x, const T& y) {
        return b < a ? b : a;
    } 
    
C ++ 17
  1. typename peut également être utilisé lors de la déclaration d'un paramètre de modèle de modèle , précédant le nom du paramètre, tout comme class .

    template <template <class T> typename U>
    void f() {
        U<int>::do_it();
        U<double>::do_it();
    }
    

taille de

Opérateur unaire qui fournit la taille en octets de son opérande, qui peut être une expression ou un type. Si l'opérande est une expression, elle n'est pas évaluée. La taille est une expression constante de type std::size_t .

Si l'opérande est un type, il doit être entre parenthèses.

  • Il est illégal d'appliquer sizeof à un type de fonction.
  • Il est illégal d'appliquer sizeof à un type incomplet, y compris le void .
  • Si sizeof est appliqué à un type de référence T& ou T&& , il est équivalent à sizeof(T) .
  • Lorsque sizeof est appliqué à un type de classe, il renvoie le nombre d'octets dans un objet complet de ce type, y compris les octets de remplissage au milieu ou à la fin. Par conséquent, une expression sizeof ne peut jamais avoir une valeur de 0. Voir la présentation des types d'objet pour plus de détails.
  • Le char , signed char et unsigned char types ont une taille de 1. A l' inverse, un octet est défini comme étant la quantité de mémoire nécessaire pour stocker une char objet. Cela ne signifie pas nécessairement 8 bits, car certains systèmes ont des objets char plus longs que 8 bits.

Si expr est une expression, sizeof( expr ) est équivalent à sizeof(T)T est le type de expr.

int a[100];
std::cout << "The number of bytes in `a` is: " << sizeof a;
memset(a, 0, sizeof a); // zeroes out the array
C ++ 11

L'opérateur sizeof... renvoie le nombre d'éléments d'un pack de paramètres.

template <class... T>
void f(T&&...) {
    std::cout << "f was called with " << sizeof...(T) << " arguments\n";
}

Mots-clés différents

annuler C ++

  1. Utilisé comme type de retour de fonction, le mot-clé void spécifie que la fonction ne renvoie pas de valeur. Utilisé pour la liste de paramètres d'une fonction, void spécifie que la fonction ne prend aucun paramètre. Lorsqu'il est utilisé dans la déclaration d'un pointeur, void spécifie que le pointeur est "universel".

  2. Si le type d'un pointeur est void *, le pointeur peut pointer sur une variable qui n'est pas déclarée avec le mot clé const ou volatile. Un pointeur vide ne peut être déréférencé que s'il est converti en un autre type. Un pointeur vide peut être converti en n'importe quel autre type de pointeur de données.

  3. Un pointeur vide peut pointer sur une fonction, mais pas sur un membre de classe en C ++.

    void vobject;   // C2182  
    void *pv;   // okay  
    int *pint; int i;  
    int main() {  
    pv = &i;  
       // Cast optional in C required in C++  
    pint = (int *)pv;  
    

Volatile C ++

  1. Un qualificateur de type que vous pouvez utiliser pour déclarer qu'un objet peut être modifié dans le programme par le matériel.

    volatile declarator ;
    

C ++ virtuel

  1. Le mot-clé virtual déclare une fonction virtuelle ou une classe de base virtuelle.

    virtual [type-specifiers] member-function-declarator  
    virtual [access-specifier] base-class-name 
    

Paramètres

  1. spécificateurs de type Spécifie le type de retour de la fonction de membre virtuel.

  2. member-function-declarator Déclare une fonction membre.

  3. spécificateur d'accès Définit le niveau d'accès à la classe de base, publique, protégée ou privée. Peut apparaître avant ou après le mot-clé virtuel.

  4. base-class-name Identifie un type de classe précédemment déclaré

ce pointeur

  1. Le pointeur this est un pointeur accessible uniquement dans les fonctions membres non statiques d'un type class, struct ou union. Il pointe vers l'objet pour lequel la fonction membre est appelée. Les fonctions membres statiques n'ont pas ce pointeur.

    this->member-identifier  
    

Le pointeur d'un objet ne fait pas partie de l'objet lui-même; cela ne se reflète pas dans le résultat d'une instruction sizeof sur l'objet. Au lieu de cela, lorsqu'une fonction membre non statique est appelée pour un objet, l'adresse du objet est transmise par le compilateur en tant qu'argument masqué à la fonction. Par exemple, l'appel de fonction suivant:

myDate.setMonth( 3 );  

can be interpreted this way:


setMonth( &myDate, 3 );  

The object's address is available from within the member function as the this pointer. Most uses of this are implicit. It is legal, though unnecessary, to explicitly use this when referring to members of the class. For example:


void Date::setMonth( int mn )  
{  
   month = mn;            // These three statements  
   this->month = mn;      // are equivalent  
   (*this).month = mn;  
}  

The expression *this is commonly used to return the current object from a member function:


return *this;  

The this pointer is also used to guard against self-reference:


if (&Object != this) {  
// do not execute in cases of self-reference 

essayer, lancer et attraper des instructions (C ++)

  1. Pour implémenter la gestion des exceptions dans C ++, utilisez les expressions try, throw et catch.
  2. Tout d'abord, utilisez un bloc try pour inclure une ou plusieurs instructions pouvant générer une exception.
  3. Une expression de lancement signale qu'une condition exceptionnelle - souvent une erreur - s'est produite dans un bloc try. Vous pouvez utiliser un objet de n'importe quel type en tant qu'opérande d'une expression de projection. Cet objet est généralement utilisé pour communiquer des informations sur l'erreur. Dans la plupart des cas, nous vous recommandons d'utiliser la classe std :: exception ou l'une des classes dérivées définies dans la bibliothèque standard. Si l'un d'entre eux n'est pas approprié, nous vous recommandons de dériver votre propre classe d'exception à partir de std :: exception.
  4. Pour gérer les exceptions pouvant être levées, implémentez un ou plusieurs blocs catch immédiatement après un bloc try. Chaque bloc catch spécifie le type d'exception qu'il peut gérer.
    MyData md;  
try {  
   // Code that could throw an exception  
   md = GetNetworkResource();  
}  
catch (const networkIOException& e) {  
   // Code that executes when an exception of type  
   // networkIOException is thrown in the try block  
   // ...  
   // Log error message in the exception object  
   cerr << e.what();  
}  
catch (const myDataFormatException& e) {  
   // Code that handles another exception type  
   // ...  
   cerr << e.what();  
}  
  
// The following syntax shows a throw expression  
MyData GetNetworkResource()  
{  
   // ...  
   if (IOSuccess == false)  
      throw networkIOException("Unable to connect");  
   // ...  
   if (readError)  
      throw myDataFormatException("Format error");   
   // ...  
}

Le code après la clause try est la section protégée du code. L'expression jeter jette, c'est-à-dire déclenche une exception. Le bloc de code après la clause catch est le gestionnaire d'exceptions. C'est le gestionnaire qui capture l'exception qui est lancée si les types dans les expressions de lancement et de capture sont compatibles.

    try {  
   throw CSomeOtherException();  
}  
catch(...) {  
   // Catch all exceptions – dangerous!!!  
   // Respond (perhaps only partially) to the exception, then  
   // re-throw to pass the exception to some other handler  
   // ...  
   throw;  
}

ami (C ++)

  1. Dans certaines circonstances, il est plus pratique d'accorder un accès au niveau des membres aux fonctions qui ne sont pas membres d'une classe ou à tous les membres d'une classe distincte. Seul l'implémenteur de classe peut déclarer qui sont ses amis. Une fonction ou une classe ne peut pas se déclarer amie d'une classe. Dans une définition de classe, utilisez le mot-clé friend et le nom d'une fonction non membre ou d'une autre classe pour lui accorder l'accès aux membres privés et protégés de votre classe. Dans une définition de modèle, un paramètre de type peut être déclaré comme ami.

  2. Si vous déclarez une fonction ami qui n'a pas été déclarée précédemment, cette fonction est exportée vers l'étendue non-classe englobante.

    class friend F  
    friend F;
    class ForwardDeclared;// Class name is known.  
    class HasFriends  
    {  
       friend int ForwardDeclared::IsAFriend();// C2039 error expected  
    };  
    

fonctions ami

  1. Une fonction amie est une fonction qui n'est pas membre d'une classe mais a accès aux membres privés et protégés de la classe. Les fonctions amis ne sont pas considérées comme membres de la classe. Ce sont des fonctions externes normales qui bénéficient de privilèges d'accès spéciaux.

  2. Les amis ne sont pas dans la portée de la classe et ils ne sont pas appelés à l'aide des opérateurs de sélection de membres (. Et ->), sauf s'ils sont membres d'une autre classe.

  3. Une fonction amie est déclarée par la classe qui accorde l'accès. La déclaration d'ami peut être placée n'importe où dans la déclaration de classe. Il n'est pas affecté par les mots-clés de contrôle d'accès.

    #include <iostream>  
    
    using namespace std;  
    class Point  
    {  
        friend void ChangePrivate( Point & );  
    public:  
        Point( void ) : m_i(0) {}  
        void PrintPrivate( void ){cout << m_i << endl; }  
    
    private:  
    int m_i;  
    };  
    
    void ChangePrivate ( Point &i ) { i.m_i++; }  
    
    int main()  
    {  
       Point sPoint;  
       sPoint.PrintPrivate();  
       ChangePrivate(sPoint);  
       sPoint.PrintPrivate();  
        // Output: 0  
               1  
    }  
    

Membres de la classe en tant qu'amis

class B;  

class A {  
public:  
   int Func1( B& b );  

private:  
   int Func2( B& b );  
};  

class B {  
private:  
int _b;  

   // A::Func1 is a friend function to class B  
   // so A::Func1 has access to all members of B  
   friend int A::Func1( B& );  
};  

int A::Func1( B& b ) { return b._b; }   // OK  
int A::Func2( B& b ) { return b._b; }   // C2248  


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow