Zoeken…


Invoering

Sleutelwoorden hebben een vaste betekenis gedefinieerd door de C ++ standaard en kunnen niet als identificatiemiddelen worden gebruikt. Het is illegaal om trefwoorden opnieuw te definiëren met behulp van de preprocessor in elke vertaaleenheid die een standaardbibliotheekkop bevat. Zoekwoorden verliezen echter hun speciale betekenis in attributen.

Syntaxis

  • asm ( string-letterlijk );
  • noexcept ( expressie ) // betekenis 1
  • noexcept ( constante-expressie ) // betekenis 2
  • noexcept // betekenis 2
  • grootte van unaire uitdrukking
  • sizeof ( type-id )
  • sizeof ... ( identifier ) // sinds C ++ 11
  • typenaam geneste-naam-specificeerder- ID // betekenis 1
  • typenaam geneste-naam-specificatiesjabloon ( opt ) eenvoudige-sjabloon-id // betekenis 1
  • typename identifier ( opt ) // betekenis 2
  • typenaam ... identifier ( opt ) // betekenis 2; sinds C ++ 11
  • typename identifier ( opt ) = type-id // betekenis 2
  • template < template-parameter-list > typename ... ( opt ) identifier ( opt ) // betekenis 3
  • template < template-parameter-list > typename identifier ( opt ) = id-expressie // betekenis 3

Opmerkingen

De volledige lijst met zoekwoorden is als volgt:

De tokens final en override zijn geen trefwoorden. Ze kunnen worden gebruikt als identificatiemiddelen en hebben een speciale betekenis alleen in bepaalde contexten.

De tokens and , and_eq , bitand , bitor , compl , not , not_eq , or , or_eq , xor en xor_eq zijn alternatieve spellingen van && , &= , & , | , ~ ! , != , || , |= , ^ en ^= , respectievelijk. De standaard behandelt ze niet als trefwoorden, maar ze zijn trefwoorden voor alle doeleinden, omdat het onmogelijk is om ze opnieuw te definiëren of te gebruiken om iets anders te betekenen dan de operatoren die ze vertegenwoordigen.

De volgende onderwerpen bevatten gedetailleerde uitleg over veel van de trefwoorden in C ++, die fundamentele doelen dienen, zoals het noemen van basistypes of het regelen van de uitvoeringsstroom.

aSM

Het sleutelwoord asm heeft één operand nodig, die letterlijk een tekenreeks moet zijn. Het heeft een door de implementatie gedefinieerde betekenis, maar wordt meestal doorgegeven aan de assembler van de implementatie, waarbij de output van de assembler wordt opgenomen in de vertaaleenheid.

De instructie asm is een definitie , geen uitdrukking , dus deze kan worden weergegeven bij block scope of namespace scope (inclusief global scope). Aangezien inline assembly echter niet kan worden beperkt door de regels van de taal C ++, verschijnt asm mogelijk niet in een constexpr functie.

Voorbeeld:

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

uitdrukkelijk

  1. Wanneer toegepast op een constructor met één argument, wordt voorkomen dat die constructor wordt gebruikt om impliciete conversies uit te voeren.

    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
    

    Sinds C ++ 11 initialisatielijsten introduceerde, kan in C ++ 11 en later explicit worden toegepast op een constructor met een willekeurig aantal argumenten, met dezelfde betekenis als in het geval met één argument.

    struct S {
        explicit S(int x, int y);
    };
    S f() {
        return {12, 34};  // ill-formed
        return S{12, 34}; // ok
    }
    
C ++ 11
  1. Wanneer toegepast op een conversiefunctie, wordt voorkomen dat die conversiefunctie wordt gebruikt om impliciete conversies uit te voeren.

    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
    

noexcept

C ++ 11
  1. Een unaire operator die bepaalt of de evaluatie van zijn operand een uitzondering kan propageren. Merk op dat de lichamen van opgeroepen functies niet worden onderzocht, dus geen noexcept kan valse negatieven opleveren. De operand wordt niet geëvalueerd.

    #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
    }
    

    Hoewel bar() in dit voorbeeld nooit een uitzondering kan noexcept(bar()) , is noexcept(bar()) nog steeds onwaar omdat het feit dat bar() een uitzondering niet kan verspreiden niet expliciet is opgegeven.

  2. Geeft bij het declareren van een functie aan of de functie een uitzondering kan propageren. Alleen, het verklaart dat de functie geen uitzondering kan propageren. Met een haakjesargument geeft het aan dat de functie al dan niet een uitzondering kan propageren, afhankelijk van de waarheidswaarde van het 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&) {}
    }
    

    In dit voorbeeld hebben we verklaard dat f4 , f5 en f6 geen uitzonderingen kunnen doorgeven. (Hoewel een uitzondering kan worden gegenereerd tijdens de uitvoering van f6 , wordt deze gevangen en mag deze niet uit de functie worden gepropageerd.) We hebben verklaard dat f2 een uitzondering kan propageren. Wanneer de noexcept specificator wordt weggelaten, is deze gelijk aan noexcept(false) , dus we hebben impliciet verklaard dat f1 en f3 uitzonderingen kunnen doorgeven, hoewel uitzonderingen niet kunnen worden gegenereerd tijdens de uitvoering van f3 .

C ++ 17

Of een functie geen noexcept is, maakt deel uit van het type functie: dat wil zeggen dat in het bovenstaande voorbeeld f1 , f2 en f3 verschillende typen hebben dan f4 , f5 en f6 . Daarom is noexcept ook belangrijk in functie-aanwijzers, sjabloonargumenten, enzovoort.

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

typename

  1. Wanneer gevolgd door een gekwalificeerde naam, geeft typename aan dat dit de naam van een type is. Dit is vaak vereist in sjablonen, met name wanneer de geneste naamspecificatie een ander afhankelijk type is dan de huidige instantie. In dit voorbeeld is std::decay<T> afhankelijk van de sjabloonparameter T , dus om het geneste type type , moeten we de hele gekwalificeerde naam typename door typename . Zie Waar en waarom moet ik de trefwoorden "sjabloon" en "typename" plaatsen voor meer informatie over deatils ?

    template <class T>
    auto decay_copy(T&& r) -> typename std::decay<T>::type;
    
  2. Introduceert een typeparameter in de aangifte van een sjabloon . In deze context is het uitwisselbaar met class .

    template <typename T>
    const T& min(const T& x, const T& y) {
        return b < a ? b : a;
    } 
    
C ++ 17
  1. typename kan ook worden gebruikt bij het declareren van een sjabloon-sjabloonparameter , voorafgaand aan de naam van de parameter, net als class .

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

De grootte van

Een unaire operator die de grootte in bytes van zijn operand oplevert, wat een expressie of een type kan zijn. Als de operand een uitdrukking is, wordt deze niet geëvalueerd. De grootte is een constante uitdrukking van het type std::size_t .

Als de operand een type is, moet deze tussen haakjes worden geplaatst.

  • Het is illegaal om sizeof toe te passen op een functietype.
  • Het is illegaal om sizeof toe te passen op een onvolledig type, inclusief void .
  • Als sizeof wordt toegepast op een referentietype T& of T&& , is dit gelijk aan sizeof(T) .
  • Wanneer sizeof wordt toegepast op een klasse type, levert dit het aantal bytes op in een compleet object van dat type, inclusief eventuele opvulbytes in het midden of aan het einde. Daarom kan een sizeof expressie nooit een waarde van 0 hebben. Zie de lay-out van objecttypen voor meer informatie.
  • De char , signed char en unsigned char hebben een grootte van 1. Omgekeerd wordt een byte gedefinieerd als de hoeveelheid geheugen die nodig is om een char object op te slaan. Het betekent niet noodzakelijkerwijs 8 bits, omdat sommige systemen char objecten hebben die langer zijn dan 8 bits.

Als expr een expressie is, is sizeof( expr ) equivalent aan sizeof(T) waarbij T het type expr is.

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

De operator sizeof... geeft het aantal elementen in een parameterpakket.

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

Verschillende sleutelwoorden

ongeldig C ++

  1. Wanneer gebruikt als een functie-retourtype, geeft het ongeldige trefwoord aan dat de functie geen waarde retourneert. Wanneer gebruikt voor de parameterlijst van een functie, geeft void aan dat de functie geen parameters gebruikt. Wanneer gebruikt in de verklaring van een aanwijzer, geeft void aan dat de aanwijzer "universeel" is.

  2. Als het type van een aanwijzer ongeldig is *, kan de aanwijzer verwijzen naar elke variabele die niet is opgegeven met het const- of vluchtige trefwoord. Een lege aanwijzer kan niet worden verwijderd als deze niet naar een ander type wordt geworpen. Een lege aanwijzer kan worden omgezet in een ander type gegevensaanwijzer.

  3. Een lege aanwijzer kan naar een functie verwijzen, maar niet naar een klassenlid in 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;  
    

Vluchtige C ++

  1. Een typekwalificatie die u kunt gebruiken om aan te geven dat een object door de hardware in het programma kan worden gewijzigd.

    volatile declarator ;
    

virtuele C ++

  1. Het virtuele sleutelwoord declareert een virtuele functie of een virtuele basisklasse.

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

parameters

  1. type-specifiers Specificeert het retourtype van de virtuele lidfunctie.

  2. member-function-declarator Declareert een ledenfunctie.

  3. access-specifier Definieert het toegangsniveau tot de basisklasse, openbaar, beveiligd of privé. Kan vóór of na het virtuele trefwoord worden weergegeven.

  4. base-class-name Identificeert een eerder gedeclareerd klassetype

deze aanwijzer

  1. De deze-aanwijzer is een aanwijzer die alleen toegankelijk is binnen de niet-statische lidfuncties van een klasse-, struct- of unietype. Het verwijst naar het object waarvoor de lidfunctie wordt aangeroepen. Statische lidfuncties hebben deze aanwijzer niet.

    this->member-identifier  
    

De aanwijzer van een object maakt geen deel uit van het object zelf; het wordt niet weerspiegeld in het resultaat van een instructie sizeof op het object. Wanneer in plaats daarvan een niet-statische lidfunctie voor een object wordt opgeroepen, wordt het adres van het object door de compiler doorgegeven als een verborgen argument voor de functie. Bijvoorbeeld de volgende functieaanroep:

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 

probeer, gooi en vang Statements (C ++)

  1. Om uitzonderingsafhandeling in C ++ te implementeren, gebruikt u try-, throw- en catch-expressies.
  2. Gebruik eerst een try-blok om een of meer statements in te sluiten die een uitzondering kunnen veroorzaken.
  3. Een worpuitdrukking geeft aan dat een uitzonderlijke toestand - vaak een fout - is opgetreden in een try-blok. U kunt een willekeurig object gebruiken als de operand van een worpexpressie. Meestal wordt dit object gebruikt om informatie over de fout te communiceren. In de meeste gevallen raden we u aan de std :: exception-klasse of een van de afgeleide klassen te gebruiken die in de standaardbibliotheek zijn gedefinieerd. Als een van deze niet geschikt is, raden we u aan uw eigen uitzonderingsklasse af te leiden uit std :: exception.
  4. Om uitzonderingen af te handelen die worden gegooid, implementeert u een of meer catch-blokken onmiddellijk na een try-blok. Elk blok blokkeert het type uitzondering dat het aankan.
    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");   
   // ...  
}

De code na de try-clausule is het bewaakte gedeelte van de code. De worpuitdrukking gooit - dat wil zeggen verhoogt - een uitzondering. Het codeblok na de catch-clausule is de uitzonderingshandler. Dit is de handler die de uitzondering opvangt die wordt gegenereerd als de typen in de worp- en vanguitdrukkingen compatibel zijn.

    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;  
}

vriend (C ++)

  1. In sommige omstandigheden is het handiger om toegang op lidniveau te verlenen aan functies die geen lid zijn van een klasse of aan alle leden in een afzonderlijke klasse. Alleen de klassenimplementator kan verklaren wie zijn vrienden zijn. Een functie of klasse kan zichzelf niet als vriend van een klasse verklaren. Gebruik in een klassedefinitie het vriend-trefwoord en de naam van een niet-lidfunctie of andere klasse om deze toegang te geven aan de privé- en beschermde leden van uw klas. In een sjabloondefinitie kan een typeparameter als vriend worden verklaard.

  2. Als u een vriendenfunctie declareert die nog niet eerder is aangegeven, wordt die functie geëxporteerd naar de omringende niet-klasse scope.

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

vriend functies

  1. Een vriendenfunctie is een functie die geen lid is van een klas maar toegang heeft tot de privé- en beschermde leden van de klas. Vriendfuncties worden niet als klasleden beschouwd; het zijn normale externe functies die speciale toegangsrechten krijgen.

  2. Vrienden bevinden zich niet in het bereik van de klas en worden niet gebeld met behulp van de ledenselectie-operatoren (. En ->) tenzij ze lid zijn van een andere klas.

  3. Een vriendenfunctie wordt verklaard door de klasse die toegang verleent. De vriendenverklaring kan overal in de klassenverklaring worden geplaatst. Het wordt niet beïnvloed door de sleutelwoorden voor toegangscontrole.

    #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  
    }  
    

Klasleden als vrienden

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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow