Funktionsüberladung so richtig?



  • hab das mal so gemacht, und wollte fragen ob es so richig und gut ist:

    int max(int a,int b)
    {
     if(a<b)
      return b;
     else
      return a;
    }
    
    int max(int a,int b,int c)
    {
     if(max(a,b)<c)
      return c;
     else
      return max(a,b);
    }
    
    int max(int a,int b,int c,int d)
    {
     if(max(a,b,c)<d)
      return d;
     else
      return max(a,b,c);
    }
    double max(double a,double b)
    {
     if(a<b)
      return b;
     else
      return a;
    }
    


  • Ohne genau hinzugucken:

    Ja stimmt so schon den Überladen heisst ja nichts anderes als unterschiedliche funktionen(in rückgabewerten, Argumentenarten und Anzahl) zuerstellen also eigentlich in Ordnung 😉



  • MartinMilbret schrieb:

    Ja stimmt so schon den Überladen heisst ja nichts anderes als unterschiedliche funktionen(in rückgabewerten, Argumentenarten und Anzahl) zuerstellen

    Das stimmt so nicht ganz. Der Rückgabewert einer Funktion gehört nicht zu ihrer Signatur, weshalb man keine Funktionen, die sich nur im Rückgabewert unterscheiden, überladen kann.

    Beispiel:

    int f(double x, double y) { ... }
    double f(double x, double y) { ... }
    
    ...
    
    int main()
    {
       ...
       double z = f(9.9, 18.18); // Fehler - Mehrdeutiger Aufruf!
       ...
    }
    

    Ansonsten ist deine Aussage aber korrekt.

    Gruß Caipi



  • oben hat ja die double funktion auch andere parameter!



  • Ich weiß nicht genau wofür du das script verwenden willst aber wenn du int double und womöglich vielleicht auch noch char werte vergleichen willst und das bei unterschiedlicher anzahl der parameter würde ich nicht so viele funktionen überladen! Sondern lieber mit einem Template mit variabler Parameterliste arbeiten.

    //template_variabel.cpp
    //ein template mit Variabler Parameterliste
    //das werte vergleicht mithilfe einer Rekursion
    //Storm 2006
    
    //Für die Variable Parameterliste
    #include <cstdarg>
    
    //Für qsort()
    #include <cstdlib>
    
    //Für cout
    #include <iostream>
    
    //maximal 100 werte
    #define buffer 100
    
    using namespace std;
    
    //##################Vergleichsfunktion für qsort#####################//
    int vergleich(const void *ptr1, const void *ptr2) {
       if( *(short *)ptr1 < *(short *)ptr2 )
          return -1;
       else if( *(short *)ptr1 > *(short *)ptr2 )
          return 1;
       else
          return 0;  /* Beide Elemente sind gleich */
    }
    
    //#########################Das Template###########################//
    namespace storm {                       //eigener namespace aufmachen
    
    template <class T> T max(T a, ...) {
    
      //Deklaration
      va_list argum_zeiger;              //zeigt auf das jeweils nächste Argument
      short zaehler = 0;                 //zählt die Argumente
      T werte[buffer];
    
      werte[zaehler] = a;
    
      //Jetzt die Werte auslesen und vergleichen
      va_start(argum_zeiger, a);
    
      while(werte[zaehler] != -1) {
      //Schleife zu auslesen (letzter wert muss immer -1 sein)
    
        zaehler++;                                  //zähler wird incrementiert
        werte[zaehler] = va_arg(argum_zeiger, T);   
        //aktueller Wert wird in array gespeichert
    
      }
    
      va_end(argum_zeiger);               //argum_zeiger wird auf NULL zurückgesetzt
    
      qsort(werte, zaehler, sizeof(T), vergleich);
      //array werte wird nach größe soriert
    
      return werte[zaehler-1];                //gröster wert wird zurückgegeben
    
    };                                      //Template zu
    
    }                                       //eigener namespace zumachen
    //#########################Ende##################################//
    
    int main() {
    
    int a, b, c, d = -1;
    int ergebnis;
    cin >> a;
    cin >> b;
    cin >> c;
    
    ergebnis = storm::max(a,b,c, d);
    
    cout << ergebnis << endl;
    
    return 0;
    
    }
    

    Dabei muss das letzte Argument aber immer -1 sein!
    Ob du jetzt jedoch int, double, float oder char übergibst ist völlig egal!
    Dieses Script rechnet sich aber wahrscheinlich nur wenn du sehr viele Werte unterschiedlichstem Typ verglaichen willst.


  • Mod

    Caipi schrieb:

    MartinMilbret schrieb:

    Ja stimmt so schon den Überladen heisst ja nichts anderes als unterschiedliche funktionen(in rückgabewerten, Argumentenarten und Anzahl) zuerstellen

    Das stimmt so nicht ganz. Der Rückgabewert einer Funktion gehört nicht zu ihrer Signatur, weshalb man keine Funktionen, die sich nur im Rückgabewert unterscheiden, überladen kann.

    Beispiel:

    int f(double x, double y) { ... }
    double f(double x, double y) { ... }
    
    ...
    
    int main()
    {
       ...
       double z = f(9.9, 18.18); // Fehler - Mehrdeutiger Aufruf!
       ...
    }
    

    Ansonsten ist deine Aussage aber korrekt.

    Gruß Caipi

    naja, so ganz korrekt ist das nicht. der begriff der signatur ist nicht standardisiert, der typ einer funktion wird bestimmt durch:
    - den return typ (bzw. void)
    - den typ ihrer parameter
    - die cv-qualifikation im falle von memberfunktionen
    - die exceptionspezifikation

    beim überladen gibt es dann bestimmte regeln, die einschränkend wirken. eine davon ist, dass funktionen, die sich nur im return-typ unterscheiden, nicht überladen werden können. das macht dein beispiel illegal, aber nicht erst beim aufruf, bereits die deklaration ist ein fehler (allerdings ist die mehrdeutigkeit, die sich beim aufruf ergäbe, der grund für diese regel).
    eine weitere regel ist z.b., dass memberfunktionen nicht mit einer statischen funktion mit denselben parametern überladen werden kann.



  • witzigerweise kann man funktionen, die sich nur in ihren exception-spezifikationen unterscheiden, überladen

    Nope. Kann man nicht. Deshalb sagt man ja auch, dass Exception-Spezifikationen eine Art "Shadow-Type System" (vgl. Exceptional C++ Style) wären. Sie gehören nicht zum Typ, bis auf manchmal.
    Nicht zum Typ gehören sie z.B. bei der Überladungsauflösung und in typedefs. Beim
    Überschreiben von virtuellen Funktionen hingegen gehören sie zum Typ.

    Es gibt zum Thema auch einen Defect Report:
    http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#92



  • camper schrieb:

    Caipi schrieb:

    MartinMilbret schrieb:

    Ja stimmt so schon den Überladen heisst ja nichts anderes als unterschiedliche funktionen(in rückgabewerten, Argumentenarten und Anzahl) zuerstellen

    Das stimmt so nicht ganz. Der Rückgabewert einer Funktion gehört nicht zu ihrer Signatur, weshalb man keine Funktionen, die sich nur im Rückgabewert unterscheiden, überladen kann.

    Beispiel:

    int f(double x, double y) { ... }
    double f(double x, double y) { ... }
    
    ...
    
    int main()
    {
       ...
       double z = f(9.9, 18.18); // Fehler - Mehrdeutiger Aufruf!
       ...
    }
    

    Ansonsten ist deine Aussage aber korrekt.

    Gruß Caipi

    naja, so ganz korrekt ist das nicht. der begriff der signatur ist nicht standardisiert, der typ einer funktion wird bestimmt durch:
    - den return typ (bzw. void)
    - den typ ihrer parameter
    - die cv-qualifikation im falle von memberfunktionen
    - die exceptionspezifikation

    beim überladen gibt es dann bestimmte regeln, die einschränkend wirken. eine davon ist, dass funktionen, die sich nur im return-typ unterscheiden, nicht überladen werden können.

    Jup. Hast Recht. Habe mich undeutlich ausgedrückt. Wollte sagen, dass der Rückgabewert, (der zu der Funktions-Signatur gehört) beim Aufruf einer Funktion nicht ermittelt werden und man desshalb keine Funktionen, die sich nur im Rückgabewert unterscheiden, überladen kann.

    das macht dein beispiel illegal, aber nicht erst beim aufruf, bereits die deklaration ist ein fehler (allerdings ist die mehrdeutigkeit, die sich beim aufruf ergäbe, der grund für diese regel).

    Auch hier hast du Recht. Habe das im Code (aus Faulheit) nicht deutlicher erwähnt...

    Gruß Caipi


Anmelden zum Antworten