Поиск…


Вступление

Ключевые слова имеют фиксированное значение, определенное стандартом C ++ и не могут использоваться как идентификаторы. Неправильно переопределять ключевые слова с использованием препроцессора в любой единицы перевода, которая включает стандартный заголовок библиотеки. Однако ключевые слова теряют свое особое значение внутри атрибутов.

Синтаксис

  • asm ( string-literal );
  • noexcept ( выражение ) // значение 1
  • noexcept ( константное выражение ) // значение 2
  • noexcept // значение 2
  • размерное унитарное выражение
  • sizeof ( type-id )
  • sizeof ... ( идентификатор ) // с C ++ 11
  • Идентификатор имени-имени-имени-имени типа // Значение 1
  • typename шаблон вложенного имени-спецификатора ( opt ) simple-template-id // значение 1
  • Идентификатор typename ( opt ) // Значение 2
  • typename ... identifier ( opt ) // значение 2; поскольку C ++ 11
  • typename identifier ( opt ) = type-id // значение 2
  • template < template-parameter-list > typename ... ( opt ) identifier ( opt ) // значение 3
  • template < template-parameter-list > идентификатор typename ( opt ) = id-expression // значение 3

замечания

Полный список ключевых слов выглядит следующим образом:

final и override токенов не являются ключевыми словами. Они могут использоваться как идентификаторы и имеют особое значение только в определенных контекстах.

Маркеры and , and_eq , bitand , bitor , compl , not , not_eq , or , or_eq , xor и xor_eq альтернативные вариантов написания && , &= , & , | , ~ ! , != , || , |= , ^ и ^= , соответственно. Стандарт не рассматривает их как ключевые слова, но они являются ключевыми словами для всех целей и целей, поскольку их невозможно переопределить или использовать для обозначения чего-либо другого, кроме операторов, которые они представляют.

Следующие темы содержат подробные объяснения многих ключевых слов на C ++, которые служат фундаментальным целям, таким как именование основных типов или контроль потока выполнения.

как м

Ключевое слово asm использует один операнд, который должен быть строковым литералом. Он имеет значение, определенное реализацией, но обычно передается ассемблеру реализации, а выход ассемблера включен в блок перевода.

Оператор asm является определением , а не выражением , поэтому он может отображаться как в области блока, так и в пространстве имен (включая глобальную область). Однако, поскольку встроенная сборка не может быть ограничена правилами языка C ++, asm не может появляться внутри функции constexpr .

Пример:

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

явный

  1. При применении к конструктору с одним аргументом предотвращает использование конструктора для выполнения неявных преобразований.

    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
    

    Поскольку C ++ 11 представил списки инициализаторов, в C ++ 11 и более поздних версиях explicit может быть применено к конструктору с любым количеством аргументов с тем же значением, что и в случае с одним аргументом.

    struct S {
        explicit S(int x, int y);
    };
    S f() {
        return {12, 34};  // ill-formed
        return S{12, 34}; // ok
    }
    
C ++ 11
  1. При применении к функции преобразования предотвращает использование функции преобразования для выполнения неявных преобразований.

    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. Унарный оператор, который определяет, может ли оценка его операнда распространять исключение. Заметим, что тела вызываемых функций не рассматриваются, поэтому noexcept может давать ложные отрицания. Операнд не оценивается.

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

    В этом примере, хотя bar() никогда не может генерировать исключение, noexcept(bar()) все равно false, поскольку тот факт, что bar() не может распространять исключение, явно не указан.

  2. При объявлении функции указывает, может ли функция распространять исключение. Один, он заявляет, что функция не может распространять исключение. С аргументом в скобках указано, что функция может или не может распространять исключение в зависимости от значения истины аргумента.

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

    В этом примере мы объявили, что f4 , f5 и f6 не могут распространять исключения. (Хотя исключение может быть выбрано во время выполнения f6 , оно поймано и не допускается к распространению из функции.) Мы объявили, что f2 может распространять исключение. Когда спецификатор noexcept опущен, он эквивалентен noexcept(false) , поэтому мы неявно объявили, что f1 и f3 могут распространять исключения, даже если исключения не могут быть фактически вызваны во время выполнения f3 .

C ++ 17

Независимо от того, является или нет функция noexcept является частью типа функции: то есть в приведенном выше примере f1 , f2 и f3 имеют разные типы из f4 , f5 и f6 . Поэтому noexcept также значим в указателях функций, аргументах шаблона и т. Д.

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

имяТипа

  1. Когда за ним следует квалифицированное имя, typename указывает, что это имя типа. Это часто требуется в шаблонах, в частности, когда вложенный спецификатор имен является зависимым типом, отличным от текущего экземпляра. В этом примере std::decay<T> зависит от параметра шаблона T , поэтому для того, чтобы назвать тип вложенного type , нам нужно префикс всего квалифицированного имени с помощью имени typename . Дополнительные сведения см. В разделе « Где и почему я должен поставить ключевые слова« template »и« typename »?

    template <class T>
    auto decay_copy(T&& r) -> typename std::decay<T>::type;
    
  2. Представляет параметр типа в объявлении шаблона . В этом контексте он является взаимозаменяемым с class .

    template <typename T>
    const T& min(const T& x, const T& y) {
        return b < a ? b : a;
    } 
    
C ++ 17
  1. typename также может использоваться при объявлении параметра шаблона шаблона , предшествующего имени параметра, точно так же, как class .

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

размер

Унарный оператор, который дает размер в байтах своего операнда, который может быть либо выражением, либо типом. Если операнд является выражением, он не оценивается. Размер представляет собой постоянное выражение типа std::size_t .

Если операнд является типом, он должен быть заключен в скобки.

  • sizeof применять sizeof к типу функции.
  • sizeof применять sizeof к неполному типу, включая void .
  • Если sizeof применяется к ссылочному типу T& или T&& , он эквивалентен sizeof(T) .
  • Когда sizeof применяется к типу класса, он дает количество байтов в полном объекте этого типа, включая любые прописные байты в середине или в конце. Поэтому выражение sizeof никогда не может иметь значение 0. Подробнее см. В описании типов объектов .
  • char , signed char и unsigned char имеют размер 1. Наоборот, байт определяется как объем памяти, необходимый для хранения объекта char . Это не обязательно означает 8 бит, так как некоторые системы имеют объекты char более 8 бит.

Если выражение expr является выражением, sizeof( expr ) эквивалентно sizeof(T) где T - тип выражения 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... дает количество элементов в пакете параметров.

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

Различные ключевые слова

void C ++

  1. Когда используется как возвращаемый тип функции, ключевое слово void указывает, что функция не возвращает значение. При использовании для списка параметров функции void указывает, что функция не принимает никаких параметров. При использовании в объявлении указателя void указывает, что указатель является «универсальным».

  2. Если тип указателя равен void *, указатель может указывать на любую переменную, которая не объявляется с ключевым словом const или volatile. Указатель void не может быть разыменован, если он не будет передан другому типу. Указатель void может быть преобразован в любой другой тип указателя данных.

  3. Указатель void может указывать на функцию, но не на член класса в 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;  
    

Неустойчивый C ++

  1. Определитель типа, который можно использовать для объявления того, что объект может быть изменен в программе аппаратным обеспечением.

    volatile declarator ;
    

виртуальный C ++

  1. Ключевое слово virtual объявляет виртуальную функцию или виртуальный базовый класс.

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

параметры

  1. Тип-спецификаторы Указывает тип возвращаемого значения виртуальной функции-члена.

  2. member-function-declarator Объявляет функцию-член.

  3. access-specifier Определяет уровень доступа к базовому классу, public, protected или private. Может отображаться до или после ключевого слова virtual.

  4. base-class-name Идентифицирует ранее объявленный тип класса

этот указатель

  1. Этот указатель является указателем, доступным только внутри нестатических функций-членов класса, структуры или типа объединения. Он указывает на объект, для которого вызывается функция-член. У статических функций-членов нет указателя.

    this->member-identifier  
    

Указатель объекта не является частью самого объекта; он не отражается в результате инструкции sizeof для объекта. Вместо этого, когда для объекта вызывается нестатическая функция-член, адрес объекта передается компилятором в качестве скрытого аргумента функции. Например, вызов следующей функции:

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 

try, throw и catch Statement (C ++)

  1. Чтобы реализовать обработку исключений в C ++, вы используете выражения try, throw и catch.
  2. Во-первых, используйте блок try, чтобы заключить одно или несколько операторов, которые могут вызывать исключение.
  3. Выражение выражает сигнал о том, что исключительное условие - часто, ошибка произошла в блоке try. Вы можете использовать объект любого типа в качестве операнда выражения throw. Как правило, этот объект используется для передачи информации об ошибке. В большинстве случаев мы рекомендуем использовать класс std :: exception или один из производных классов, определенных в стандартной библиотеке. Если один из них не подходит, мы рекомендуем вам получить свой собственный класс исключения из std :: exception.
  4. Чтобы обрабатывать исключения, которые могут быть выбраны, реализовать один или несколько блоков catch сразу после блока try. Каждый блок catch определяет тип исключения, с которым он может обращаться.
    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");   
   // ...  
}

Код после предложения try является защищенной секцией кода. Выражение броска бросает - то есть повышает - исключение. Блок кода после предложения catch является обработчиком исключений. Это обработчик, который ловит исключение, которое выбрасывается, если типы в выражениях throw и catch совместимы.

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

друг (C ++)

  1. В некоторых случаях удобнее предоставлять доступ на уровне членов к функциям, которые не являются членами класса или ко всем членам в отдельном классе. Только разработчик класса может объявить, кто его друзья. Функция или класс не могут объявить себя другом любого класса. В определении класса используйте ключевое слово friend и имя функции, не являющейся членом, или другого класса, чтобы предоставить ему доступ к закрытым и защищенным членам вашего класса. В определении шаблона параметр типа может быть объявлен как друг.

  2. Если вы объявляете функцию друга, которая ранее не была объявлена, эта функция экспортируется в охватываемую область неклассификации.

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

функции друга

  1. Функция друга - это функция, которая не является членом класса, но имеет доступ к закрытым и защищенным членам класса. Дружеские функции не считаются членами класса; они являются нормальными внешними функциями, которым предоставляются особые привилегии доступа.

  2. Друзья не входят в сферу действия класса, и они не вызывается с использованием операторов выбора элементов (. И ->), если они не являются членами другого класса.

  3. Функция друга объявляется классом, предоставляющим доступ. Объявление друга может быть помещено в любом месте объявления класса. К ним не относятся ключевые слова управления доступом.

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

Члены класса в качестве друзей

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
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow