Namensräume
Varianten
Aktionen

Benutzerdefinierte Konvertierungsfunktion

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

Ermöglicht implizite Konvertierung oder explizite Konvertierung von einem Klassentyp in einen anderen Typ.

Inhalt

[bearbeiten] Syntax

Eine Konvertierungsfunktion wird wie eine nicht-statische Memberfunktion oder eine Member-Funktionstemplate ohne Parameter, ohne expliziten Rückgabetyp und mit dem Namen der Form deklariert

operator conversion-type-id (1)
explicit operator conversion-type-id (2) (seit C++11)
explicit ( expression ) operator conversion-type-id (3) (seit C++20)
1) Deklariert eine benutzerdefinierte Konvertierungsfunktion, die an allen impliziten und expliziten Konvertierungen teilnimmt.
2) Deklariert eine benutzerdefinierte Konvertierungsfunktion, die nur an direkter Initialisierung und expliziten Konvertierungen teilnimmt.
3) Deklariert eine benutzerdefinierte Konvertierungsfunktion, die bedingt explizit ist.

conversion-type-id ist ein type-id, mit der Ausnahme, dass Funktions- und Array-Operatoren [] oder () in seinem Deklarator nicht zulässig sind (daher erfordert die Konvertierung in Typen wie Zeiger auf Array einen Typ-Alias/typedef oder ein Identitätstemplate: siehe unten). Unabhängig von typedef kann conversion-type-id keinen Array- oder Funktionstyp darstellen.

Obwohl der Rückgabetyp in der Deklaration einer benutzerdefinierten Konvertierungsfunktion nicht zulässig ist, kann die decl-specifier-seq der Deklarationsgrammatik vorhanden sein und neben type-specifier oder dem Schlüsselwort static jede Spezifikation enthalten. Insbesondere neben explicit sind auch die Spezifikationen inline, virtual, constexpr(seit C++11), consteval(seit C++20) und friend zulässig (beachten Sie, dass friend einen qualifizierten Namen erfordert: friend A::operator B();).

Wenn eine solche Memberfunktion in der Klasse X deklariert wird, führt sie eine Konvertierung von X in conversion-type-id durch.

struct X
{
    // implicit conversion
    operator int() const { return 7; }
 
    // explicit conversion
    explicit operator int*() const { return nullptr; }
 
    // Error: array operator not allowed in conversion-type-id
//  operator int(*)[3]() const { return nullptr; }
 
    using arr_t = int[3];
    operator arr_t*() const { return nullptr; } // OK if done through typedef
//  operator arr_t () const; // Error: conversion to array not allowed in any case
};
 
int main()
{
    X x;
 
    int n = static_cast<int>(x);   // OK: sets n to 7
    int m = x;                     // OK: sets m to 7
 
    int* p = static_cast<int*>(x); // OK: sets p to null
//  int* q = x; // Error: no implicit conversion
 
    int (*pa)[3] = x;  // OK
}

[bearbeiten] Erklärung

Die benutzerdefinierte Konvertierungsfunktion wird in der zweiten Stufe der impliziten Konvertierung aufgerufen, die aus null oder einem Konstruktor oder null oder einer benutzerdefinierten Konvertierungsfunktion besteht.

Wenn sowohl Konvertierungsfunktionen als auch Konvertierungskonstruktoren für eine benutzerdefinierte Konvertierung verwendet werden können, werden die Konvertierungsfunktionen und Konstruktoren bei der Überladungsauflösung in Kontexten der Kopierinitialisierung und Referenzinitialisierung berücksichtigt, aber in Kontexten der direkten Initialisierung werden nur die Konstruktoren berücksichtigt.

struct To
{
    To() = default;
    To(const struct From&) {} // converting constructor
};
 
struct From
{
    operator To() const {return To();} // conversion function
};
 
int main()
{
    From f;
    To t1(f);  // direct-initialization: calls the constructor
    // Note: if converting constructor is not available, implicit copy constructor
    // will be selected, and conversion function will be called to prepare its argument
 
//  To t2 = f; // copy-initialization: ambiguous
    // Note: if conversion function is from a non-const type, e.g.
    // From::operator To();, it will be selected instead of the ctor in this case
 
    To t3 = static_cast<To>(f); // direct-initialization: calls the constructor
    const To& r = f;            // reference-initialization: ambiguous
}

Konvertierungsfunktionen in die eigene (möglicherweise cv-qualifizierte) Klasse (oder eine Referenz darauf), in die Basisklasse der eigenen Klasse (oder eine Referenz darauf) und in den Typ void können definiert werden, aber nicht als Teil der Konvertierungssequenz ausgeführt werden, außer in einigen Fällen durch virtuelle Weiterleitung.

struct D;
 
struct B
{
    virtual operator D() = 0;
};
 
struct D : B
{
    operator D() override { return D(); }
};
 
int main()
{
    D obj;
    D obj2 = obj; // does not call D::operator D()
    B& br = obj;
    D obj3 = br;  // calls D::operator D() through virtual dispatch
}

Sie kann auch über die Memberfunktionsaufrufsyntax aufgerufen werden.

struct B {};
 
struct X : B
{
    operator B&() { return *this; };
};
 
int main()
{
    X x;
    B& b1 = x;                  // does not call X::operatorB&()
    B& b2 = static_cast<B&>(x); // does not call X::operatorB&
    B& b3 = x.operator B&();    // calls X::operatorB&
}

Beim expliziten Aufruf der Konvertierungsfunktion ist conversion-type-id "gierig": Es ist die längste Zeichenfolge, die potenziell eine conversion-type-id bilden kann (einschließlich Attribute, falls vorhanden)(seit C++11).

& x.operator int * a; // error: parsed as & (x.operator int*) a,
                      //           not as & (x.operator int) * a
 
operator int [[noreturn]] (); // error: noreturn attribute applied to a type

Der Platzhalter auto kann in conversion-type-id verwendet werden, was einen abgeleiteten Rückgabetyp angibt.

struct X
{
    operator int(); // OK
    operator auto() -> short; // error: trailing return type not part of syntax
    operator auto() const { return 10; } // OK: deduced return type
    operator decltype(auto)() const { return 10l; } // OK: deduced return type
};

Hinweis: Eine Konvertierungsfunktionstemplate darf keinen abgeleiteten Rückgabetyp haben.

(seit C++14)

Konvertierungsfunktionen können geerbt werden und virtuell sein, aber nicht statisch. Eine Konvertierungsfunktion in der abgeleiteten Klasse verbirgt keine Konvertierungsfunktion in der Basisklasse, es sei denn, sie konvertieren in denselben Typ.

Eine Konvertierungsfunktion kann eine Template-Memberfunktion sein, z. B. std::auto_ptr<T>::operator auto_ptr<Y>. Siehe Member-Templates und Template-Argument-Deduktion für anwendbare Sonderregeln.

[bearbeiten] Schlüsselwörter

operator

[bearbeiten] Fehlerberichte

Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
CWG 296 C++98 Konvertierungsfunktionen könnten statisch sein sie können nicht als statisch deklariert werden
CWG 2016 C++98 Konvertierungsfunktionen konnten keine Rückgabetypen angeben,
aber die Typen sind in conversion-type-id vorhanden
Rückgabetypen können nicht in den
Deklarationsspezifikationen von Konvertierungsfunktionen
CWG 2175 C++11 war es unklar, ob die [[noreturn]] in
operator int [[noreturn]] (); als Teil von
noptr-declarator (eines Funktionsdeklarators) oder conversion-type-id geparst wird
es wird als Teil von
conversion-type-id