C++
Słowa kluczowe
Szukaj…
Wprowadzenie
Słowa kluczowe mają ustalone znaczenie zdefiniowane przez standard C ++ i nie mogą być używane jako identyfikatory. Redefiniowanie słów kluczowych przy użyciu preprocesora w dowolnej jednostce tłumaczeniowej zawierającej standardowy nagłówek biblioteki jest nielegalne. Jednak słowa kluczowe tracą swoje specjalne znaczenie w atrybutach.
Składnia
- asm ( literał-ciąg );
- noexcept ( wyrażenie ) // znaczenie 1
- noexcept ( wyrażenie stałe ) // znaczenie 2
- noexcept // co oznacza 2
- wielkość wyrażenia jednoargumentowego
- sizeof ( identyfikator typu )
- sizeof ... ( identyfikator ) // od C ++ 11
- typename identyfikator zagnieżdżony-nazwa- identyfikator // znaczenie 1
- typename nested-name-specifier template ( opt ) simple-template-id // znaczenie 1
- identyfikator nazwy typu ( opt ) // znaczenie 2
- typename ... identyfikator ( opt ) // znaczenie 2; od C ++ 11
- identyfikator nazwy typu ( opt ) = identyfikator typu // znaczenie 2
- szablon < lista-parametrów-listy > nazwa_typu ... ( opt ) identyfikator ( opt ) // znaczenie 3
- szablon < lista-parametrów-listy > typename identifier ( opt ) = id-wyrażenie // znaczenie 3
Uwagi
Pełna lista słów kluczowych jest następująca:
-
alignas
(od C ++ 11) -
alignof
(od C ++ 11) -
asm
-
auto
: od C ++ 11 , przed C ++ 11 -
bool
-
break
-
case
-
catch
-
char
-
char16_t
(od C ++ 11) -
char32_t
(od C ++ 11) -
class
-
const
-
constexpr
(od C ++ 11) -
const_cast
-
continue
-
decltype
(od C ++ 11) -
default
-
delete
celu zarządzania pamięcią , dla funkcji (od C ++ 11) -
do
-
double
-
dynamic_cast
-
else
-
enum
-
explicit
-
export
-
extern
jako specyfikator deklaracji , w specyfikacji powiązania , dla szablonów -
false
-
float
-
for
-
friend
-
goto
-
if
-
inline
dla funkcji , dla przestrzeni nazw (od C ++ 11), dla zmiennych (od C ++ 17) -
int
-
long
-
mutable
-
namespace
-
new
-
noexcept
(od C ++ 11) -
nullptr
(od C ++ 11) -
operator
-
private
-
protected
-
public
-
register
-
reinterpret_cast
-
return
-
short
-
signed
-
sizeof
-
static
-
static_assert
(od C ++ 11) -
static_cast
-
struct
-
switch
-
template
-
this
-
thread_local
(od C ++ 11) -
throw
-
true
-
try
-
typedef
-
typeid
-
typename
-
union
-
unsigned
-
using
aby zmienić nazwę , alias przestrzeni nazw , alias typu -
virtual
dla funkcji , dla klas podstawowych -
void
-
volatile
-
wchar_t
-
while
final
i override
tokeny nie są słowami kluczowymi. Mogą być używane jako identyfikatory i mają specjalne znaczenie tylko w niektórych kontekstach.
Tokeny and
, and_eq
, bitand
, bitor
, compl
, not
, not_eq
, or
, or_eq
, xor
, a xor_eq
alternatywne pisowni &&
, &=
, &
, |
, ~
!
, !=
, ||
, |=
, ^
i ^=
odpowiednio. Standard nie traktuje ich jako słów kluczowych, ale są słowami kluczowymi do wszystkich celów i celów, ponieważ nie można ich przedefiniować ani używać ich w znaczeniu innym niż operatory, które reprezentują.
Poniższe tematy zawierają szczegółowe objaśnienia wielu słów kluczowych w C ++, które służą podstawowym celom, takim jak nazywanie podstawowych typów lub kontrolowanie przebiegu wykonywania.
jako M
asm
kluczowe asm
przyjmuje pojedynczy operand, który musi być dosłowny. Ma znaczenie zdefiniowane w implementacji, ale zwykle jest przekazywane do asemblera implementacji, a dane wyjściowe asemblera są włączane do jednostki tłumaczącej.
Instrukcja asm
jest definicją , a nie wyrażeniem , więc może pojawiać się w zakresie bloków lub w przestrzeni nazw (w tym w zakresie globalnym). Ponieważ jednak zestaw wbudowany nie może być ograniczony regułami języka C ++, asm
może nie pojawić się w funkcji constexpr
.
Przykład:
[[noreturn]] void halt_system() {
asm("hlt");
}
wyraźny
Po zastosowaniu do konstruktora z jednym argumentem uniemożliwia temu konstruktorowi wykonywanie niejawnych konwersji.
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
Ponieważ C ++ 11 wprowadził listy inicjalizujące, w C ++ 11 i późniejszych,
explicit
można zastosować do konstruktora z dowolną liczbą argumentów, o takim samym znaczeniu jak w przypadku pojedynczego argumentu.struct S { explicit S(int x, int y); }; S f() { return {12, 34}; // ill-formed return S{12, 34}; // ok }
Po zastosowaniu do funkcji konwersji zapobiega wykorzystywaniu tej funkcji konwersji do niejawnych konwersji.
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
nie
Jednoargumentowy operator, który określa, czy ocena jego operandu może propagować wyjątek. Zauważ, że ciała wywoływanych funkcji nie są badane, więc
noexcept
może dawać fałszywych negatywów. Operand nie jest oceniany.#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 }
W tym przykładzie, mimo że
bar()
nigdy nie możenoexcept(bar())
wyjątku,noexcept(bar())
jest nadal fałszywy, ponieważ fakt, żebar()
nie może propagować wyjątku, nie został wyraźnie określony.Podczas deklarowania funkcji określa, czy funkcja może propagować wyjątek. Sam deklaruje, że funkcja nie może propagować wyjątku. Za pomocą argumentu w nawiasach deklaruje, że funkcja może lub nie może propagować wyjątku w zależności od wartości prawdy argumentu.
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&) {} }
W tym przykładzie zadeklarowaliśmy, że
f4
,f5
if6
nie mogą propagować wyjątków. (Chociaż wyjątek może zostać zgłoszony podczas wykonywaniaf6
, jest on wychwytywany i nie może się propagować poza funkcją.) Zadeklarowaliśmy, żef2
może propagować wyjątek. Gdy specyfikatornoexcept
zostanie pominięty, jest to równoważne znoexcept(false)
, więc domyślnie zadeklarowaliśmy, żef1
if3
mogą propagować wyjątki, nawet jeśli wyjątki nie mogą być faktycznie zgłaszane podczas wykonywaniaf3
.
To, czy funkcja nie jest noexcept
jest częścią typu funkcji: to znaczy w powyższym przykładzie f1
, f2
i f3
mają różne typy od f4
, f5
i f6
. Dlatego noexcept
ma również znaczenie w przypadku wskaźników funkcji, argumentów szablonów i tak dalej.
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
Wpisz imię
Po nazwie kwalifikowanej
typename
określa, że jest to nazwa typu. Jest to często wymagane w szablonach, w szczególności gdy specyfikator zagnieżdżonej nazwy jest typem zależnym innym niż bieżąca instancja. W tym przykładzie,std::decay<T>
zależy od szablonu parametrT
, tak aby wymienić zagnieżdżony typtype
, musimy poprzedzić całą kwalifikowaną nazwę ztypename
. Aby dowiedzieć się więcej o deatilach, zobacz Gdzie i dlaczego muszę umieszczać słowa kluczowe „szablon” i „typename”?template <class T> auto decay_copy(T&& r) -> typename std::decay<T>::type;
Wprowadza parametr typu do deklaracji szablonu . W tym kontekście jest wymienny z
class
.template <typename T> const T& min(const T& x, const T& y) { return b < a ? b : a; }
typename
może być również używana podczas deklarowania parametru szablonu szablonu , poprzedzającego nazwę parametru, podobnie jakclass
.template <template <class T> typename U> void f() { U<int>::do_it(); U<double>::do_it(); }
rozmiar
Jednoargumentowy operator, który podaje rozmiar w bajtach swojego operandu, który może być wyrażeniem lub typem. Jeśli operand jest wyrażeniem, nie jest analizowane. Rozmiar jest stałym wyrażeniem typu std::size_t
.
Jeśli operand jest typem, musi być nawiasowany.
- Stosowanie
sizeof
do typu funkcji jest nielegalne. - Stosowanie
sizeof
do niekompletnego typu, w tymvoid
jest niezgodne z prawem. - Jeśli sizeof jest zastosowany do typu odniesienia
T&
lubT&&
, jest on równoważnysizeof(T)
. - Zastosowanie
sizeof
do typu klasy daje liczbę bajtów w pełnym obiekcie tego typu, w tym bajty wypełniające na środku lub na końcu. Dlatego wyrażeniesizeof
nigdy nie może mieć wartości 0. Aby uzyskać więcej informacji, zobacz układ typów obiektów . - Typy
char
,signed char
iunsigned char
mają rozmiar 1. I odwrotnie, bajt jest definiowany jako ilość pamięci wymaganej do przechowywania obiektuchar
. Nie musi to oznaczać 8 bitów, ponieważ niektóre systemy mają obiektychar
dłuższe niż 8 bitów.
Jeśli wyrażenie jest wyrażeniem, sizeof(
wyrażenie )
jest równoważne sizeof(T)
gdzie T
jest rodzajem wyrażenia.
int a[100];
std::cout << "The number of bytes in `a` is: " << sizeof a;
memset(a, 0, sizeof a); // zeroes out the array
Operator sizeof...
zwraca liczbę elementów w pakiecie parametrów.
template <class... T>
void f(T&&...) {
std::cout << "f was called with " << sizeof...(T) << " arguments\n";
}
Różne słowa kluczowe
void C ++
Gdy jest używane jako typ zwracany przez funkcję, słowo kluczowe void określa, że funkcja nie zwraca wartości. W przypadku użycia dla listy parametrów funkcji, void określa, że funkcja nie przyjmuje parametrów. W przypadku użycia w deklaracji wskaźnika, void określa, że wskaźnik jest „uniwersalny”.
Jeśli typ wskaźnika jest nieważny *, wskaźnik może wskazywać dowolną zmienną, która nie jest zadeklarowana za pomocą słowa kluczowego const lub volatile. Wskaźnika pustki nie można wyrejestrować, chyba że zostanie on rzutowany na inny typ. Wskaźnik pustki można przekształcić w dowolny inny wskaźnik danych.
Wskaźnik pustki może wskazywać na funkcję, ale nie na element klasy w 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;
Lotny C ++
Kwalifikator typu, którego można użyć do zadeklarowania, że obiekt może być modyfikowany w programie przez sprzęt.
volatile declarator ;
wirtualny C ++
Wirtualne słowo kluczowe deklaruje wirtualną funkcję lub wirtualną klasę podstawową.
virtual [type-specifiers] member-function-declarator virtual [access-specifier] base-class-name
Parametry
specyfikatory typu Określa typ zwracanej funkcji wirtualnego elementu członkowskiego.
deklarator funkcji członka Deklaruje funkcję członka.
specyfikator dostępu Definiuje poziom dostępu do klasy podstawowej, publicznej, chronionej lub prywatnej. Może pojawić się przed wirtualnym słowem kluczowym lub po nim.
base-class-name Identyfikuje wcześniej zadeklarowany typ klasy
ten wskaźnik
Ten wskaźnik jest wskaźnikiem dostępnym tylko w ramach niestatycznych funkcji składowych typu klasy, struktury lub unii. Wskazuje obiekt, dla którego wywoływana jest funkcja członka. Statyczne funkcje składowe nie mają tego wskaźnika.
this->member-identifier
Wskaźnik tego obiektu nie jest częścią samego obiektu; nie jest odzwierciedlone w wyniku instrukcji sizeof na obiekcie. Zamiast tego, gdy wywoływana jest niestatyczna funkcja elementu dla obiektu, adres obiektu jest przekazywany przez kompilator jako ukryty argument funkcji. Na przykład następujące wywołanie funkcji:
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 i catch Instrukcje (C ++)
- Aby zaimplementować obsługę wyjątków w C ++, używasz wyrażeń try, throw i catch.
- Najpierw użyj bloku try, aby dołączyć jedną lub więcej instrukcji, które mogą zgłaszać wyjątek.
- Wyrażenie wyrzucenia sygnalizuje, że wystąpił wyjątkowy warunek - często błąd - w bloku try. Możesz użyć obiektu dowolnego typu jako argumentu wyrażenia rzutowania. Zazwyczaj ten obiekt służy do przekazywania informacji o błędzie. W większości przypadków zalecamy użycie klasy std :: wyjątek lub jednej z klas pochodnych zdefiniowanych w bibliotece standardowej. Jeśli któryś z nich nie jest odpowiedni, zalecamy wyprowadzenie własnej klasy wyjątków ze std :: wyjątek.
- Aby obsłużyć wyjątki, które mogą zostać zgłoszone, zaimplementuj jeden lub więcej bloków catch bezpośrednio po bloku try. Każdy blok catch określa typ wyjątku, który może obsłużyć.
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");
// ...
}
Kod po klauzuli try jest strzeżoną sekcją kodu. Wyrażenie rzucania rzuca - to znaczy podnosi - wyjątek. Blok kodu po klauzuli catch to moduł obsługi wyjątków. Jest to moduł obsługi, który przechwytuje wyjątek zgłaszany, jeśli typy w wyrażeniach throw i catch są kompatybilne.
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;
}
przyjaciel (C ++)
W niektórych okolicznościach wygodniej jest przyznać dostęp na poziomie członka do funkcji, które nie są członkami klasy lub wszystkim członkom w osobnej klasie. Tylko osoba wdrażająca klasy może zadeklarować, kim są jego przyjaciele. Funkcja lub klasa nie może zadeklarować się jako przyjaciel dowolnej klasy. W definicji klasy użyj słowa kluczowego „przyjaciel” i nazwy funkcji nieczłonkowskiej lub innej klasy, aby przyznać jej dostęp do prywatnych i chronionych członków twojej klasy. W definicji szablonu parametr typu można zadeklarować jako przyjaciela.
Jeśli zadeklarujesz funkcję przyjaciela, która nie została wcześniej zadeklarowana, funkcja ta zostanie wyeksportowana do obejmującego nieklasowego zakresu.
class friend F friend F; class ForwardDeclared;// Class name is known. class HasFriends { friend int ForwardDeclared::IsAFriend();// C2039 error expected };
funkcje przyjaciela
Funkcja przyjaciela to funkcja, która nie jest członkiem klasy, ale ma dostęp do prywatnych i chronionych członków klasy. Funkcje znajomych nie są uważane za członków klasy; są to normalne funkcje zewnętrzne, które mają specjalne uprawnienia dostępu.
Znajomi nie są objęci zakresem klasy i nie są wywoływani za pomocą operatorów wyboru członków (. I ->), chyba że są członkami innej klasy.
Funkcja znajomego jest deklarowana przez klasę, która udziela dostępu. Deklarację znajomego można umieścić w dowolnym miejscu deklaracji klasy. Nie wpływają na to słowa kluczowe kontroli dostępu.
#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 }
Członkowie klasy jako przyjaciele
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