Sök…


Introduktion

Nyckelord har en fast betydelse definierad av C ++ -standarden och kan inte användas som identifierare. Det är olagligt att omdefiniera nyckelord med hjälp av förprocessorn i någon översättningsenhet som innehåller en standardbibliotekshuvud. Emellertid förlorar nyckelord sin speciella betydelse inuti attribut.

Syntax

  • asm ( string-letteral );
  • noexcept ( uttryck ) // betyder 1
  • noexcept ( konstant uttryck ) // betyder 2
  • noexcept // betyder 2
  • storlek av unary-expression
  • storlek av ( typ-id )
  • sizeof ... ( identifierare ) // sedan C ++ 11
  • typnamn kapslad identifierare identifierare // betydelse 1
  • typnamn kapslad-namn-specifik mall ( opt ) enkel-mall-id // betydelse 1
  • Typename identifierare (opt) // betyder 2
  • typnamn ... identifierare ( opt ) // betyder 2; sedan C ++ 11
  • Typename identifierare (opt) = typ-id // betyder 2
  • mall < mall-parameter-lista > typnamn ... ( opt ) identifierare ( opt ) // betydelse 3
  • mall <mall-parameterlista> Typename identifierare (opt) = id-uttryck // vilket betyder 3

Anmärkningar

Den fullständiga listan med nyckelord är enligt följande:

Tokenens final och override är inte nyckelord. De kan användas som identifierare och har speciell betydelse endast i vissa sammanhang.

Tokens and , and_eq , bitand , bitor , compl , not , not_eq or , or_eq , xor och xor_eq är alternativa stavningar för && , &= , & , | , ~ ! , != , || , |= , ^ respektive ^= . Standarden behandlar dem inte som nyckelord, men de är nyckelord för alla syften, eftersom det är omöjligt att omdefiniera dem eller använda dem för att betyda något annat än de operatörer de representerar.

Följande ämnen innehåller detaljerade förklaringar av många av nyckelorden i C ++, som tjänar grundläggande syften som att namnge grundtyper eller kontrollera körningsflödet.

asm

asm nyckelordet tar en enda operand, som måste vara en strängbokstavlig. Den har en implementeringsdefinierad betydelse, men överförs vanligtvis till implementeringens monterare, varvid monterarens utgång införlivas i översättningsenheten.

asm uttalandet är en definition , inte ett uttryck , så det kan visas antingen i blockomfång eller namnområde (inklusive global räckvidd). Eftersom inline-montering inte kan begränsas av reglerna för C ++ asm kanske asm inte visas i en constexpr funktion.

Exempel:

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

explicit

  1. När den tillämpas på en konstruktör med ett enda argument, förhindrar den konstruktören från att utföra implicita konverteringar.

    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
    

    Eftersom C ++ 11 införde initialiseringslistor, i C ++ 11 och senare, kan explicit tillämpas på en konstruktör med valfritt antal argument, med samma betydelse som i fallet med en enda argument.

    struct S {
        explicit S(int x, int y);
    };
    S f() {
        return {12, 34};  // ill-formed
        return S{12, 34}; // ok
    }
    
C ++ 11
  1. När den tillämpas på en konverteringsfunktion förhindrar den att konverteringsfunktionen används för att utföra implicita konverteringar.

    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. En unary operatör som avgör om utvärderingen av dess operand kan föröka ett undantag. Observera att kropparna med kallade funktioner inte undersöks, så noexcept kan ge falska negativ. Operanden utvärderas inte.

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

    I detta exempel, även om bar() aldrig kan kasta ett undantag, är noexcept(bar()) fortfarande felaktigt eftersom det faktum att bar() inte kan sprida ett undantag inte har uttryckligen angetts.

  2. När du deklarerar en funktion anger du om funktionen kan sprida ett undantag eller inte. Enbart förklarar den att funktionen inte kan sprida ett undantag. Med ett parenteserat argument förklarar det att funktionen kan eller inte kan sprida ett undantag beroende på sanningsvärdet för argumentet.

    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&) {}
    }
    

    I det här exemplet har vi förklarat att f4 , f5 och f6 inte kan sprida undantag. (Även om ett undantag kan kastas under körning av f6 , fångas det och får inte sprida sig ur funktionen.) Vi har förklarat att f2 kan sprida ett undantag. När noexcept specifikatorn utelämnas motsvarar den noexcept(false) , så vi har implicit förklarat att f1 och f3 kan sprida undantag, även om undantag faktiskt inte kan kastas under exekveringen av f3 .

C ++ 17

Huruvida en funktion är noexcept eller inte är en del av funktionens typ: det vill säga i exemplet ovan har f1 , f2 och f3 olika typer från f4 , f5 och f6 . Därför är noexcept också viktigt i funktionspekare, mallargument osv.

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. När det följs av ett kvalificerat namn anger typename att det är namnet på en typ. Detta krävs ofta i mallar, i synnerhet när den kapslade namnspecifikationen är en annan beroende typ än den aktuella inställningen. I det här exemplet beror std::decay<T> på mallparametern T , så för att namnge den kapslade type måste vi prefixera hela kvalificerade namnet med typename . För mer deatils, se Var och varför måste jag sätta "mall" och "typnamn" nyckelorden?

    template <class T>
    auto decay_copy(T&& r) -> typename std::decay<T>::type;
    
  2. Introducerar en typparameter i deklarationen av en mall . I detta sammanhang är det utbytbart med class .

    template <typename T>
    const T& min(const T& x, const T& y) {
        return b < a ? b : a;
    } 
    
C ++ 17
  1. typename kan också användas när du deklarerar en mallmallparameter , före parameterns namn, precis som class .

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

storlek av

En unary operatör som ger storleken i byte på sin operand, vilket kan vara antingen ett uttryck eller en typ. Om operanden är ett uttryck utvärderas den inte. Storleken är ett konstant uttryck för typen std::size_t .

Om operanden är en typ måste den ha parentes.

  • Det är olagligt att tillämpa sizeof på en funktionstyp.
  • Det är olagligt att tillämpa sizeof på en ofullständig typ, inklusive void .
  • Om sizeof tillämpas på en referenstyp T& eller T&& , motsvarar den sizeof(T) .
  • När sizeof tillämpas på en sizeof ger det antalet byte i ett komplett objekt av den typen, inklusive eventuella stoppningsbyte i mitten eller i slutet. Därför kan ett sizeof uttryck aldrig ha ett värde på 0. Se layout av objekttyper för mer information.
  • char , signed char och unsigned char typer har en storlek på 1. Omvänt definieras en byte som mängden minne som krävs för att lagra ett char objekt. Det betyder inte nödvändigtvis 8 bitar, eftersom vissa system har char objekt som är längre än 8 bitar.

Om expr är ett uttryck, är sizeof( expr ) ekvivalent med sizeof(T) där T är typen av 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

sizeof... ger antalet element i ett parameterpaket.

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

Olika nyckelord

ogiltig C ++

  1. När det används som en funktion avkastningstyp, anger det ogiltiga nyckelordet att funktionen inte returnerar ett värde. När det används för en funktions parameterlista anger void att funktionen inte tar några parametrar. När det används i deklarationen för en pekare, anger tomrum att pekaren är "universal".

  2. Om en pekartyp är ogiltig * kan pekaren peka på alla variabler som inte deklareras med const eller volatile nyckelord. En ogiltig pekare kan inte avskaffas om den inte kastas till en annan typ. En ogiltig pekare kan konverteras till någon annan typ av datapekare.

  3. En ogiltig pekare kan peka på en funktion, men inte till en klassmedlem i 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;  
    

Flyktiga C ++

  1. En typkvalificering som du kan använda för att förklara att ett objekt kan modifieras i programmet av hårdvaran.

    volatile declarator ;
    

virtuell C ++

  1. Det virtuella nyckelordet förklarar en virtuell funktion eller en virtuell basklass.

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

parametrar

  1. typspecifikationer Anger returtypen för den virtuella medlemsfunktionen.

  2. medlem-funktion-deklarator Förklarar en medlemsfunktion.

  3. access-specificier Definierar åtkomstnivån till basklassen, offentligt, skyddat eller privat. Kan visas före eller efter det virtuella nyckelordet.

  4. basklassklassnamn Identifierar en tidigare deklarerad klasstyp

den här pekaren

  1. Pekaren är en pekare som endast är tillgänglig inom de icke-statiska medlemsfunktionerna av en klass, struktur eller facklig typ. Den pekar på objektet för vilket medlemsfunktionen kallas. Statiska medlemsfunktioner har inte den här pekaren.

    this->member-identifier  
    

Ett objekt är den här pekaren är inte en del av själva objektet; det återspeglas inte i resultatet av en storlekof-uttalande på objektet. I stället, när en icke-statisk medlemsfunktion kallas för ett objekt, skickas objektets adress av kompilatorn som ett doldt argument till funktionen. Följande funktion ringer till exempel:

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 

prova, kasta och fånga uttalanden (C ++)

  1. För att implementera undantagshantering i C ++ använder du försök, kasta och fånga uttryck.
  2. Använd först ett försöksblock för att bifoga ett eller flera uttalanden som kan kasta ett undantag.
  3. Ett kastuttryck signalerar att ett exceptionellt tillstånd - ofta ett fel - har inträffat i ett försöksblock. Du kan använda ett objekt av valfri typ som operand för ett kastuttryck. Vanligtvis används detta objekt för att kommunicera information om felet. I de flesta fall rekommenderar vi att du använder std :: undantagsklassen eller en av de härledda klasserna som definieras i standardbiblioteket. Om en av dessa inte är lämplig, rekommenderar vi att du hämtar din egen undantagsklass från std :: undantag.
  4. För att hantera undantag som kan kastas, implementera ett eller flera fångstblock omedelbart efter ett försöksblock. Varje fångstblock anger vilken typ av undantag den kan hantera.
    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");   
   // ...  
}

Koden efter provklausulen är den skyddade delen av koden. Kastuttrycket kastar - det vill säga höjer - ett undantag. Kodblocket efter fångstklausulen är undantagshanteraren. Det här är hanteraren som fångar det undantag som kastas om typerna i kast- och fångstuttryck är kompatibla.

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

vän (C ++)

  1. Under vissa omständigheter är det bekvämare att ge medlemmarnas åtkomst till funktioner som inte är medlemmar i en klass eller för alla medlemmar i en separat klass. Endast klassimplementören kan förklara vem dess vänner är. En funktion eller klass kan inte förklara sig som en vän till någon klass. I en klassdefinition använder du vän-nyckelordet och namnet på en icke-medlemsfunktion eller annan klass för att ge den åtkomst till de privata och skyddade medlemmarna i din klass. I en malldefinition kan en typparameter förklaras som en vän.

  2. Om du förklarar en vänfunktion som inte tidigare har deklarerats exporteras den funktionen till det bifogade icke-klassade omfånget.

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

vänfunktioner

  1. En vänfunktion är en funktion som inte är medlem i en klass men har tillgång till klassens privata och skyddade medlemmar. Vänfunktioner anses inte klassmedlemmar; de är normala externa funktioner som ges speciella åtkomstbehörigheter.

  2. Vänner är inte inom klassens omfattning och de kallas inte med medlemmarvalsoperatörer (. Och ->) om de inte är medlemmar i en annan klass.

  3. En vänfunktion deklareras av klassen som ger åtkomst. Vändeklarationen kan placeras var som helst i klassdeklarationen. Det påverkas inte av nyckelorden för åtkomstkontroll.

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

Klassmedlemmar som vänner

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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow