C++
Schlüsselwörter
Suche…
Einführung
Schlüsselwörter haben eine durch den C ++ - Standard definierte feste Bedeutung und können nicht als Bezeichner verwendet werden. Es ist nicht zulässig, Schlüsselwörter mithilfe des Präprozessors in einer Übersetzungseinheit neu zu definieren, die einen Standard-Bibliothekskopf enthält. Schlüsselwörter verlieren jedoch ihre besondere Bedeutung in Attributen.
Syntax
- asm ( String-Literal );
- noexcept ( Ausdruck ) // Bedeutung 1
- noexcept ( konstanter Ausdruck ) // Bedeutung 2
- noexcept // bedeutung 2
- sizeof unary-expression
- sizeof ( Typ-ID )
- sizeof ... ( Bezeichner ) // seit C ++ 11
- Type - Name verschachtelt-name-Bezeichner Kennung // 1 Bedeutung
- Typname Vorlage für geschachtelte Namen (optional) ( opt ) simple-template-id // Bedeutung 1
- Typname Kennung (opt) // Bedeutung 2
- Typname ... Bezeichner ( Opt ) // Bedeutung 2; seit C ++ 11
- Bezeichner Typname ( opt ) = Typ-ID // Bedeutung 2
- template < template-parameter-list > typename ... ( opt ) Bezeichner ( opt ) // Bedeutung 3
- template <template-Parameter-Liste> Typname Kennung (opt) = id-Ausdruck // Bedeutung 3
Bemerkungen
Die vollständige Liste der Keywords lautet wie folgt:
-
alignas
(seit C ++ 11) -
alignof
(seit C ++ 11) -
asm
-
auto
: seit C ++ 11 vor C ++ 11 -
bool
-
break
-
case
-
catch
-
char
-
char16_t
(seit C ++ 11) -
char32_t
(seit C ++ 11) -
class
-
const
-
constexpr
(seit C ++ 11) -
const_cast
-
continue
-
decltype
(seit C ++ 11) -
default
-
delete
für die Speicherverwaltung für Funktionen (seit C ++ 11) -
do
-
double
-
dynamic_cast
-
else
-
enum
-
explicit
-
export
-
extern
als Deklarationsspezifizierer , in der Verknüpfungsspezifikation für Vorlagen -
false
-
float
-
for
-
friend
-
goto
-
if
-
inline
für Funktionen , für Namespaces (seit C ++ 11), für Variablen (seit C ++ 17) -
int
-
long
-
mutable
-
namespace
-
new
-
noexcept
(seit C ++ 11) -
nullptr
(seit C ++ 11) -
operator
-
private
-
protected
-
public
-
register
-
reinterpret_cast
-
return
-
short
-
signed
-
sizeof
-
static
-
static_assert
(seit C ++ 11) -
static_cast
-
struct
-
switch
-
template
-
this
-
thread_local
(seit C ++ 11) -
throw
-
true
-
try
-
typedef
-
typeid
-
typename
-
union
-
unsigned
-
using
, um einen Namen erneut zu deklarieren, einen Aliasnamen oder einen Aliasnamen zu definieren -
virtual
für Funktionen , für Basisklassen -
void
-
volatile
-
wchar_t
-
while
Das Token final
und override
sind keine Schlüsselwörter. Sie können als Bezeichner verwendet werden und haben nur in bestimmten Zusammenhängen eine besondere Bedeutung.
Die Token and
, and_eq
, bitand
, bitor
, compl
, not
, not_eq
or
or_eq
, xor
und xor_eq
sind alternative Schreibweisen von &&
, &=
, &
, |
, ~
!
, !=
, ||
, |=
, ^
und ^=
. Der Standard behandelt sie nicht als Schlüsselwörter, aber sie sind Schlüsselwörter für alle Absichten und Zwecke, da es unmöglich ist, sie neu zu definieren oder sie zu verwenden, um etwas anderes als die von ihnen repräsentierten Operatoren zu bedeuten.
Die folgenden Themen enthalten ausführliche Erklärungen zu vielen Schlüsselwörtern in C ++, die grundlegenden Zwecken dienen, z. B. zum Benennen von Basistypen oder zum Steuern des Ausführungsflusses.
asm
Das Schlüsselwort asm
akzeptiert einen einzelnen Operanden, der ein String-Literal sein muss. Es hat eine implementierungsdefinierte Bedeutung, wird jedoch normalerweise an den Assembler der Implementierung übergeben, wobei die Ausgabe des Assemblers in die Übersetzungseinheit integriert wird.
Die asm
Anweisung ist eine Definition und kein Ausdruck . Daher kann sie entweder im Blockbereich oder im Namespace-Bereich (einschließlich des globalen Bereichs) stehen. Da die Inline-Assembly jedoch nicht durch die Regeln der C ++ - Sprache eingeschränkt werden kann, erscheint asm
möglicherweise nicht in einer constexpr
Funktion.
Beispiel:
[[noreturn]] void halt_system() {
asm("hlt");
}
explizit
Bei Anwendung auf einen Konstruktor mit einem einzigen Argument wird verhindert, dass dieser Konstruktor für implizite Konvertierungen verwendet wird.
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
Seit C ++ 11 Initializer-Listen eingeführt hat, kann
explicit
in C ++ 11 und höher auf einen Konstruktor mit einer beliebigen Anzahl von Argumenten angewendet werden, die dieselbe Bedeutung haben wie im Fall eines einzelnen Arguments.struct S { explicit S(int x, int y); }; S f() { return {12, 34}; // ill-formed return S{12, 34}; // ok }
Bei Anwendung auf eine Konvertierungsfunktion wird verhindert, dass diese Konvertierungsfunktion für implizite Konvertierungen verwendet wird.
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
Ein unärer Operator, der bestimmt, ob die Auswertung seines Operanden eine Ausnahme auslösen kann. Beachten Sie, dass die Körper der aufgerufenen Funktionen nicht untersucht werden, sodass
noexcept
falsche Negativenoexcept
kann. Der Operand wird nicht ausgewertet.#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 }
Auch wenn
bar()
niemals eine Ausnahmenoexcept(bar())
kann, istnoexcept(bar())
immer noch falsch, da die Tatsache, dassbar()
keine Ausnahmenoexcept(bar())
kann, nicht explizit angegeben wurde.Gibt bei der Deklaration einer Funktion an, ob die Funktion eine Ausnahme weitergeben kann. Allein erklärt es, dass die Funktion keine Ausnahme weitergeben kann. Mit einem Argument in Klammern erklärt es, dass die Funktion abhängig vom Wahrheitswert des Arguments eine Ausnahme ausgeben kann oder nicht.
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 diesem Beispiel haben wir erklärt, dass
f4
,f5
undf6
keine Ausnahmen verbreiten können. (Obwohl eine Ausnahme während der Ausführung vonf6
ausgelöst werden kann, wird sie abgefangen und darf sich nicht aus der Funktion ausbreiten.) Wir haben erklärt, dassf2
eine Ausnahmef2
kann. Wenn dernoexcept
weggelassen wird, entspricht ernoexcept(false)
haben wir implizit erklärt, dassf1
undf3
Ausnahmen ausbreiten können, obwohl Ausnahmen während der Ausführung vonf3
nicht wirklich ausgelöst werden können.
Ob eine Funktion keine noexcept
ist oder nicht, ist Teil des Funktionstyps: Im obigen Beispiel unterscheiden sich f1
, f2
und f3
von f4
, f5
und f6
. Daher ist noexcept
auch für Funktionszeiger, Vorlagenargumente usw. von Bedeutung.
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
Modellname
Wenn er von einem qualifizierten Namen gefolgt wird, gibt
typename
an, dass es sich um den Namen eines Typs handelt. Dies ist häufig in Vorlagen erforderlich, insbesondere wenn der geschachtelte Namensbezeichner ein von der aktuellen Instanziierung abweichender Typ ist. In diesem Beispielstd::decay<T>
ist abhängig von dem Template - ParameternT
, so um den verschachtelte Art zu nennentype
, wir die gesamten qualifizierten Namen mit Präfix müssentypename
. Weitere Informationen finden Sie unter Wo und warum muss ich die Schlüsselwörter "template" und "typename" eingeben?template <class T> auto decay_copy(T&& r) -> typename std::decay<T>::type;
Führt einen Typparameter in die Deklaration einer Vorlage ein . In diesem Zusammenhang ist es mit der
class
austauschbar.template <typename T> const T& min(const T& x, const T& y) { return b < a ? b : a; }
typename
kann auch verwendet werden, wenn ein template-Template-Parameter deklariert wird , der wie derclass
dem Namen des Parameters vorangeht.template <template <class T> typename U> void f() { U<int>::do_it(); U<double>::do_it(); }
Größe von
Ein unärer Operator, der die Größe seines Operanden in Bytes ermittelt, der entweder ein Ausdruck oder ein Typ sein kann. Wenn der Operand ein Ausdruck ist, wird er nicht ausgewertet. Die Größe ist ein konstanter Ausdruck des Typs std::size_t
.
Wenn der Operand ein Typ ist, muss er in Klammern gesetzt werden.
- Es ist nicht
sizeof
,sizeof
auf einen Funktionstyp anzuwenden. - Es ist nicht
sizeof
,sizeof
auf einen unvollständigen Typ, einschließlichvoid
, anzuwenden. - Wenn sizeof auf einen Referenztyp
T&
oderT&&
angewendet wird, entspricht essizeof(T)
. - Wenn
sizeof
auf einen Klassentyp angewendet wird, gibt es die Anzahl der Bytes in einem vollständigen Objekt dieses Typs an, einschließlich der Auffüllbytes in der Mitte oder am Ende. Daher kann einsizeof
Ausdruck niemals den Wert 0 haben. Weitere Informationen finden Sie im Layout der Objekttypen . - Die Typen
char
,signed char
undunsigned char
haben eine Größe von 1. Umgekehrt wird ein Byte als die Menge Speicher definiert, die zum Speichern eineschar
Objekts erforderlich ist. Es muss nicht unbedingt 8 Bit bedeuten, da einige Systeme habenchar
Objekte länger als 8 Bit.
Wenn expr ein Ausdruck ist, ist sizeof(
expr )
äquivalent zu sizeof(T)
wobei T
der Typ von expr ist.
int a[100];
std::cout << "The number of bytes in `a` is: " << sizeof a;
memset(a, 0, sizeof a); // zeroes out the array
Der Operator sizeof...
gibt die Anzahl der Elemente in einem Parameterpaket an.
template <class... T>
void f(T&&...) {
std::cout << "f was called with " << sizeof...(T) << " arguments\n";
}
Unterschiedliche Schlüsselwörter
C ++ ungültig machen
Bei Verwendung als Funktionsrückgabetyp gibt das Schlüsselwort void an, dass die Funktion keinen Wert zurückgibt. Wenn void für die Parameterliste einer Funktion verwendet wird, gibt void an, dass die Funktion keine Parameter annimmt. Bei der Deklaration eines Zeigers gibt void an, dass der Zeiger "universal" ist.
Wenn der Zeigertyp void * ist, kann der Zeiger auf eine beliebige Variable zeigen, die nicht mit dem Schlüsselwort const oder volatile deklariert ist. Ein ungültiger Zeiger kann nicht dereferenziert werden, wenn er nicht in einen anderen Typ umgewandelt wird. Ein ungültiger Zeiger kann in einen beliebigen anderen Datenzeiger-Typ umgewandelt werden.
Ein ungültiger Zeiger kann auf eine Funktion zeigen, aber nicht auf ein Klassenmitglied 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;
Flüchtiges C ++
Ein Typqualifizierer, mit dem Sie angeben können, dass ein Objekt im Programm von der Hardware geändert werden kann.
volatile declarator ;
virtuelles C ++
Das virtuelle Schlüsselwort deklariert eine virtuelle Funktion oder eine virtuelle Basisklasse.
virtual [type-specifiers] member-function-declarator virtual [access-specifier] base-class-name
Parameter
Typspezifizierer Gibt den Rückgabetyp der virtuellen Memberfunktion an.
member-function-declarator Deklariert eine Member-Funktion.
Zugriffsspezifizierer Definiert die Zugriffsebene für die Basisklasse (öffentlich, geschützt oder privat). Kann vor oder nach dem virtuellen Schlüsselwort angezeigt werden.
Basisklassenname Gibt einen zuvor deklarierten Klassentyp an
dieser Zeiger
Dieser Zeiger ist ein Zeiger, auf den nur innerhalb der nicht statischen Memberfunktionen einer Klasse, Struktur oder eines Unionstyps zugegriffen werden kann. Es zeigt auf das Objekt, für das die Memberfunktion aufgerufen wird. Statische Memberfunktionen haben diesen Zeiger nicht.
this->member-identifier
Der Zeiger eines Objekts ist nicht Teil des Objekts selbst; Sie wird nicht im Ergebnis einer Anweisung sizeof für das Objekt berücksichtigt. Wenn stattdessen eine nicht statische Member-Funktion für ein Objekt aufgerufen wird, wird die Adresse des Objekts vom Compiler als verstecktes Argument an die Funktion übergeben. Zum Beispiel den folgenden Funktionsaufruf:
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
Anweisungen versuchen, werfen und abfangen (C ++)
- Um die Ausnahmebehandlung in C ++ zu implementieren, verwenden Sie try, throw und catch-Ausdrücke.
- Verwenden Sie zunächst einen try-Block, um eine oder mehrere Anweisungen einzuschließen, die eine Ausnahme auslösen können.
- Ein Wurfausdruck signalisiert, dass in einem try-Block eine außergewöhnliche Bedingung - oft ein Fehler - aufgetreten ist. Sie können ein Objekt eines beliebigen Typs als Operanden eines Wurfausdrucks verwenden. Normalerweise wird dieses Objekt verwendet, um Informationen zu dem Fehler zu übermitteln. In den meisten Fällen wird empfohlen, die std :: ausnahmeklasse oder eine der abgeleiteten Klassen zu verwenden, die in der Standardbibliothek definiert sind. Wenn eine davon nicht geeignet ist, empfehlen wir Ihnen, Ihre eigene Exception-Klasse von std :: exception abzuleiten.
- Implementieren Sie einen oder mehrere catch-Blöcke unmittelbar nach einem try-Block, um möglicherweise ausgelöste Ausnahmen zu behandeln. Jeder catch-Block gibt den Typ der Ausnahme an, die er behandeln kann.
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");
// ...
}
Der Code nach der try-Klausel ist der überwachte Codeabschnitt. Der Wurfausdruck wirft - das heißt, löst eine Ausnahme aus. Der Codeblock nach der catch-Klausel ist der Ausnahmehandler. Dies ist der Handler, der die Ausnahme abfängt, die ausgelöst wird, wenn die Typen in den Wurf- und Fangausdrücken kompatibel sind.
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;
}
Freund (C ++)
Unter bestimmten Umständen ist es günstiger, auf Mitgliedsebene Zugriff auf Funktionen zu gewähren, die keine Mitglieder einer Klasse sind, oder auf alle Mitglieder einer separaten Klasse. Nur der Klassenimplementierer kann angeben, wer seine Freunde sind. Eine Funktion oder Klasse kann sich nicht als Freund einer Klasse deklarieren. Verwenden Sie in einer Klassendefinition das Schlüsselwort friend und den Namen einer Nichtmitgliedsfunktion oder einer anderen Klasse, um diesem Zugriff auf die privaten und geschützten Mitglieder Ihrer Klasse zu gewähren. In einer Vorlagendefinition kann ein Typparameter als Freund deklariert werden.
Wenn Sie eine Friend-Funktion deklarieren, die zuvor nicht deklariert wurde, wird diese Funktion in den umschließenden nicht-Klassenbereich exportiert.
class friend F friend F; class ForwardDeclared;// Class name is known. class HasFriends { friend int ForwardDeclared::IsAFriend();// C2039 error expected };
Freundesfunktionen
Eine Friend-Funktion ist eine Funktion, die kein Mitglied einer Klasse ist, aber Zugriff auf die privaten und geschützten Member der Klasse hat. Freunde-Funktionen werden nicht als Klassenmitglieder betrachtet. Es handelt sich hierbei um normale externe Funktionen, die über spezielle Zugriffsrechte verfügen.
Freunde sind nicht im Gültigkeitsbereich der Klasse und werden nicht mit den Elementauswahloperatoren (. Und ->) aufgerufen, es sei denn, sie sind Mitglieder einer anderen Klasse.
Eine Friend-Funktion wird von der Klasse deklariert, die den Zugriff gewährt. Die Friend-Deklaration kann an beliebiger Stelle in der Klassendeklaration platziert werden. Es ist von den Schlüsselwörtern für die Zugriffskontrolle nicht betroffen.
#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 }
Klassenmitglieder als Freunde
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