Implizite Konvertierungsoperatoren

sheel

I love Asm
Hi

ein Typoperator einer Klasse bewirkt, dass Objekte dieser Klasse auch als Werte von diesem Typ "verstanden" werden können.

Beispiel ohne zuerst:
C++:
class MeineKlasse
{
public:
    int gib4() { return 4; }
    int gib9() { return 9; }
};

...

MeineKlasse k;
int i;

i = k.gib4(); //i ist jetzt natürlich 4
i = k.gib9(); //i ist jetzt natürlich 9

i = k; //das ergibt aber einen Compilerfehler, weil ein Objekt von MeineKlasse in kein int reinpasst
Beispiel mit:
C++:
class MeineKlasse
{
public:
    int gib4() { return 4; }
    int gib9() { return 9; }
    operator int() { return 10; }
};

...

MeineKlasse k;
int i;

i = k.gib4(); //i ist jetzt natürlich 4
i = k.gib9(); //i ist jetzt natürlich 9

i = k; //i ist jetzt 10
k ist zwar noch immer ein Klassenobjekt, von dem man Methoden aufrufen kann usw., aber falls man es wie eine int-Variable verwenden will geht das jetzt auch. Welchen Wert es haben soll wird durch den operator int bestimmt (der auch eine volle Methode ist, nur mit einem speziellen Namen. Also der Wert muss nicht fix sein oder so, man kann drin alles machen, es muss am Schluss nur ein int returnt werden).

Wann man das machen soll? Ganz einfach, wann es Sinn macht :) Hast du eine Klasse, die vom Sinn her einen Wert darstellt und mit anderen "normalen" Werte direkt verrechnet werden soll etc.? ...

Zum "implizit": Beim i=k oben muss man nicht dazuschreiben, dass k in dieser Anweisung als int behandelt werden will. Der Compiler kennt den operator int, und weiß dass k eigentlich nicht zu i passt aber mit dem operator schon, also wirds verwendet. Es gibt auch eine explizite Variante: "explicit" zum operator dazuschreiben, dann:
C++:
i = k; //Compilerfehler trotz Operator
i = (int)k; //Jetzt gehts, weil man mit dem Cast nochmal sagt dass es jetzt als int gebraucht wird.
 
Zuletzt bearbeitet:

Joe1903

Mitglied
Hi

ein Typoperator einer Klasse bewirkt, dass Objekte dieser Klasse auch als Werte von diesem Typ "verstanden" werden können.

Beispiel ohne zuerst:
C++:
class MeineKlasse
{
public:
    int gib4() { return 4; }
    int gib9() { return 9; }
};

...

MeineKlasse k;
int i;

i = k.gib4(); //i ist jetzt natürlich 4
i = k.gib9(); //i ist jetzt natürlich 9

i = k; //das ergibt aber einen Compilerfehler, weil ein Objekt von MeineKlasse in kein int reinpasst
Beispiel mit:
C++:
class MeineKlasse
{
public:
    int gib4() { return 4; }
    int gib9() { return 9; }
    operator int() { return 10; }
};

...

MeineKlasse k;
int i;

i = k.gib4(); //i ist jetzt natürlich 4
i = k.gib9(); //i ist jetzt natürlich 9

i = k; //i ist jetzt 10
k ist zwar noch immer ein Klassenobjekt, von dem man Methoden aufrufen kann usw., aber falls man es wie eine int-Variable verwenden will geht das jetzt auch. Welchen Wert es haben soll wird durch den operator int bestimmt (der auch eine volle Methode ist, nur mit einem speziellen Namen. Also der Wert muss nicht fix sein oder so, man kann drin alles machen, es muss am Schluss nur ein int returnt werden).

Wann man das machen soll? Ganz einfach, wann es Sinn macht :) Hast du eine Klasse, die vom Sinn her einen Wert darstellt und mit anderen "normalen" Werte direkt verrechnet werden soll etc.? ...

Ich habe hier dieses Konstrukt und möchte herausfinden, was operator _IMQSspServiceBase_FetchedFunction(void) genau macht:

C++:
...

extern "C"
{
 typedef void (* _IMQSspServiceBase_FetchedFunction)(...);
}

...

class IMQSspServiceBase
{
 public:

 class SspFunction
 {
 public:

 SspFunction(const char * publicName,const char * name)
  throw();

 operator _IMQSspServiceBase_FetchedFunction(void)
  throw(OS390_BASE_EX_BASE);

 private:
 SspFunction(
 const SspFunction &)
 throw(); // not allowed
 void operator = (const SspFunction &)
 throw(); // not allowed
...

inline
IMQSspServiceBase::SspFunction::
 operator _IMQSspServiceBase_FetchedFunction(void)
 throw(OS390_BASE_EX_BASE)
{
 TC_TRACE_ENTER(OS390_BASE_TRC_GRP, this, "IMQSspServiceBase::"
  "SspFunction::operator _IMQSspServiceBase_FetchedFunction");
 if (m_fct == 0)
 {
  fetch();
 }
...

Ich meine, es konvertiert die Klasse IMQSspServiceBase zu _IMQSspServiceBase_FetchedFunction(void) auf die Objekte von IMQSspServiceBase::SspFunction zugreifen zu können.
Aber ich bin noch ziemlich neu in dem Gebiet.. Das ist doch implizite Typumwandlung oder?
 

sheel

I love Asm
Die eigentliche Verwendung zeigst du nicht, daher weiß ich nicht ob es implizit oder explizit ist.
Aber prinzipiell möglich ist es damit, ja.
 

sheel

I love Asm
Casten, also "i = (int)k;", kann man immer. Ob es ohne Cast auch geht, also wenn man den Compiler das zusammensuchen lässt, hängt von "explicit" ab (mit explicit = geht nicht).

Da bei dir kein explicit steht gehen beide Varianten, mit und ohne Cast. Das meinte ich, ich weiß nicht was du verwendest.
 

cwriter

Erfahrenes Mitglied
P.S: Bei explizit muss man doch "explicit" angeben oder?
Ob es ohne Cast auch geht, also wenn man den Compiler das zusammensuchen lässt, hängt von "explicit" ab (mit explicit = geht nicht).
Ich meine, es konvertiert die Klasse IMQSspServiceBase zu _IMQSspServiceBase_FetchedFunction(void) auf die Objekte von IMQSspServiceBase::SspFunction zugreifen zu können.
Aber ich bin noch ziemlich neu in dem Gebiet.. Das ist doch implizite Typumwandlung oder?
Genau genommen ist es semantisch nicht einmal eine Typumwandlung, sondern nur syntaktisch (wie man eine Klasse semantisch auf eine Funktion wandeln können soll, ist mir schleierhaft (und übrigens auch recht hässlich)).
@sheel hat es schon gesagt, hier andersrum:
Das keyword "explict" sagt nur, dass die Typkonvertierung nicht implizit passieren darf. Das macht z.B. Sinn, wenn du in einer Klasse die Rationalen Zahlen repräsentierst und eine Konvertierung auf int erlauben willst: Ein cast auf int hat höchstwahrscheinlich einen Datenverlust zur Folge, und um den Nutzer deiner Klasse von unbeabsichtigten Datenverlusten zu bewahren, verbietet "explict" eine stille Konvertierung. Mit casts kann man das aber erzwingen.
Typkonvertierungsfunktionen sind aber weder explizit noch implizit, sondern die Nutzung davon. (Daher gehört "explicit" auch in den Header).
C++:
int a = (int)'abc'; //explizit (d.h. mit cast)
int b = 'abc'; //Implizit: Der Standard sagt, dass Zeichenliterale int sind.

cwriter

/EDIT: Vielleicht ein bisschen genauer: Man spricht zwar von "expliziten Konvertierungsfunktionen", meint aber eigentlich "Konvertierungsfunktionen, deren Nutzung man explizit verlangen muss". Im Gegensatz dazu sind "implizite Konvertierungsfunktionen" eigentlich "Konvertierungsfunktionen, die auch implizit (zusätzlich zu explizit) benutzt werden können". Die Anwendung davon (die Konvertierung selbst) kann bei impliziten )bzw. expliziten) Konvertierungsfunktionen explizit und implizit (bzw. ausschliesslich explizit) sein.
Das eigentliche Problem hier ist die Nomenklatur, da eine Konvertierungsfunktion mit "explicit" bezeichnet wird, aber eigentlich "usage is explicit only" gemeint ist. (Denn genaugenommen werden ja beide Funktionen explizit definiert, auch wenn implizit definierte Konvertierungen auch interessant wären (also quasi Nutzung einer undefinierten Konvertierung lässt den Compiler eine Lösung finden) :) ).
 
Zuletzt bearbeitet: