Frage

Wir alle wissen, dass Sie eine Funktion entsprechend den Parametern überlasten können:

int mul(int i, int j) { return i*j; }
std::string mul(char c, int n) { return std::string(n, c); } 

Können Sie eine Funktion Überlastung nach dem Rückgabewert? Definieren Sie eine Funktion, die verschiedene Dinge wieder nach, wie der Rückgabewert verwendet wird:

int n = mul(6, 3); // n = 18
std::string s = mul(6, 3); // s = "666"
// Note that both invocations take the exact same parameters (same types)

Sie können davon ausgehen, der erste Parameter zwischen 0-9, keine Notwendigkeit, den Eingang oder haben keine Fehlerbehandlung zu überprüfen.

War es hilfreich?

Lösung

class mul
{
public:
    mul(int p1, int p2)
    {
        param1 = p1;
        param2 = p2;
    }
    operator int ()
    {
        return param1 * param2;
    }

    operator std::string ()
    {
        return std::string(param2, param1 + '0');
    }

private:
    int param1;
    int param2;
};

Nicht, dass ich das würde verwenden.

Andere Tipps

Sie haben den Compiler zu sagen, welche Version zu verwenden. In C ++, können Sie es drei Arten tun.

Explizit die Anrufe unterscheiden, indem Sie

Sie betrogen etwas, weil Sie eine ganze Zahl auf eine Funktion wartet auf ein Zeichen gesendet, und schickte zu Unrecht die Nummer sechs, wenn der char-Wert von ‚6‘ nicht 6, sondern 54 (in ASCII):

std::string mul(char c, int n) { return std::string(n, c); }

std::string s = mul(6, 3); // s = "666"

Die richtige Lösung wäre, natürlich,

std::string s = mul(static_cast<char>(54), 3); // s = "666"

Dies war erwähnenswert, glaube ich, auch wenn Sie die Lösung nicht wollen.

unterscheiden Explizit die Anrufe von Dummy-Zeiger

Sie können einen Dummy-Parameter zu einzelnen Funktionen hinzuzufügen, so dass die Compiler zwingen, die richtigen Funktionen zu wählen. Der einfachste Weg ist es, ein NULL-Zeiger dummy des Typs für die Rück gewünschten senden:

int mul(int *, int i, int j) { return i*j; }
std::string mul(std::string *, char c, int n) { return std::string(n, c); }

, die mit dem Code verwendet werden kann:

int n = mul((int *) NULL, 6, 3); // n = 18
std::string s = mul((std::string *) NULL, 54, 3); // s = "666"

Explizit die Anrufe unterscheiden von Templating den Rückgabewert

Mit dieser Lösung schaffen wir eine „Dummy“ Funktion mit Code, der nicht kompiliert werden, wenn instanziiert:

template<typename T>
T mul(int i, int j)
{
   // If you get a compile error, it's because you did not use
   // one of the authorized template specializations
   const int k = 25 ; k = 36 ;
}

Sie finden diese Funktion beachten Sie wird nicht kompiliert, was eine gute Sache ist, weil wir nur verwenden, um einige eingeschränkte Funktionen durch Template-Spezialisierung wollen:

template<>
int mul<int>(int i, int j)
{
   return i * j ;
}

template<>
std::string mul<std::string>(int i, int j)
{
   return std::string(j, static_cast<char>(i)) ;
}

So wird der folgende Code kompilieren:

int n = mul<int>(6, 3); // n = 18
std::string s = mul<std::string>(54, 3); // s = "666"

Aber diese werden nicht:

short n2 = mul<short>(6, 3); // error: assignment of read-only variable ‘k’

Explizit die Anrufe unterscheiden von Templating den Rückgabewert, 2

  
    

Hey, du betrogen, auch!

  

Richtig, habe ich die gleichen Parameter für die beiden „überlastet“ Funktionen nutzen. Aber Sie haben den Betrug beginnen (siehe oben) ...

^ _ ^

Noch gravierender ist, wenn Sie verschiedene Parameter haben müssen, dann werden Sie mehr Code schreiben, und dann explizit die richtigen Typen verwenden müssen, wenn die Funktionen Aufruf Unklarheiten zu vermeiden:

// For "int, int" calls
template<typename T>
T mul(int i, int j)
{
   // If you get a compile error, it's because you did not use
   // one of the authorized template specializations
   const int k = 25 ; k = 36 ;
}

template<>
int mul<int>(int i, int j)
{
   return i * j ;
}

// For "char, int" calls
template<typename T>
T mul(char i, int j)
{
   // If you get a compile error, it's because you did not use
   // one of the authorized template specializations
   const int k = 25 ; k = 36 ;
}

template<>
std::string mul<std::string>(char i, int j)
{
   return std::string(j, (char) i) ;
}

Und dieser Code würde als solche verwendet werden:

int n = mul<int>(6, 3); // n = 18
std::string s = mul<std::string>('6', 3); // s = "666"

Und die folgende Zeile ein:

short n2 = mul<short>(6, 3); // n = 18

Würde noch nicht kompiliert werden.

Fazit

Ich liebe C ++ ...

- p

Wenn Sie machen mul wollen statt einer Klasse eine reelle Funktion sein, könnten Sie nur eine Zwischenklasse verwenden:

class StringOrInt
{
public:
    StringOrInt(int p1, int p2)
    {
        param1 = p1;
        param2 = p2;
    }
    operator int ()
    {
        return param1 * param2;
    }

    operator std::string ()
    {
        return std::string(param2, param1 + '0');
    }

private:
    int param1;
    int param2;
};

StringOrInt mul(int p1, int p2)
{
    return StringOrInt(p1, p2);
}

Auf diese Weise können Sie Dinge wie mul als Funktion in std Algorithmen übergeben:

int main(int argc, char* argv[])
{
    vector<int> x;
    x.push_back(3);
    x.push_back(4);
    x.push_back(5);
    x.push_back(6);

    vector<int> intDest(x.size());
    transform(x.begin(), x.end(), intDest.begin(), bind1st(ptr_fun(&mul), 5));
    // print 15 20 25 30
    for (vector<int>::const_iterator i = intDest.begin(); i != intDest.end(); ++i)
        cout << *i << " ";
    cout << endl;

    vector<string> stringDest(x.size());
    transform(x.begin(), x.end(), stringDest.begin(), bind1st(ptr_fun(&mul), 5));
    // print 555 5555 55555 555555
    for (vector<string>::const_iterator i = stringDest.begin(); i != stringDest.end(); ++i)
        cout << *i << " ";
    cout << endl;

    return 0;
}

Nein.

Sie können nicht durch Rückgabewert überlasten, da der Anrufer nichts tun (oder nichts) mit ihm. Bedenken Sie:

mul(1, 2);

Der Rückgabewert wird einfach weggeworfen, so gibt es keine Möglichkeit, es allein eine Überlastung basierend auf Rückgabewert wählen kann.

Verwenden Sie implizite Konvertierung in einem in zwischen Klasse.

class BadIdea
{
  public:
    operator string() { return "silly"; }
    operator int() { return 15; }
};

BadIdea mul(int, int)

Sie erhalten die Idee, schreckliche Idee aber.

Lassen Sie mul als eine Klasse, mul (x, y) den Konstruktor, und einige Casting-Betreiber überlasten.

Sie können keine Funktion Überlastung auf der Grundlage der Rückgabewert nur.

Während jedoch streng genommen ist dies nicht eine überladene Funktion, können Sie von Ihrer Funktion zurückgeben als Ergebnis eine Instanz einer Klasse, die die Umwandlung Betreiber überlastet.

Ich nehme an, Sie könnte es einige seltsame Art Foo zurück, die nur die Parameter erfasst und dann hat Foo einen impliziten Operator int und Operator-String, und es wäre „Arbeit“, obwohl es nicht wirklich überlasten würde, eher ein implizites Umwandlung Trick.

Hmmm, die folgenden Code Projekt Artikel scheint zu tun, was du bist nach. Muss Magie;)

Kurz und knapp, ist die Antwort NEIN. In C ++ sind die Anforderungen:

1: Namen von Funktionen muss die gleiche sein
2: Satz von Argumenten muss unterscheiden
* Der Rückgabetyp kann gleich oder verschieden sein

//This is not valid
    int foo();
    float foo();

    typedef int Int;

    int foo(int j);
    int foo(Int j);

//Valid:
   int foo(int j);
   char* foo(char * s);
   int foo(int j, int k);
   float foo(int j, float k);
   float foo(float j, float k);

Soweit ich weiß, kann man nicht (großes Mitleid, obwohl ...). Als Abhilfe können Sie ein ‚out‘ Parameter stattdessen definieren und dass man überlasten.

Nicht in C ++. Was Sie im obigen Beispiel bekommen würde der zurückgegebene Wert sein, der einen int Guss in etwas ist string verstehen kann, höchstwahrscheinlich ein char. Welche ASCII 18 oder "Gerätesteuerung 2" sein würde.

Sie können die Funktors Lösung oben verwenden. C ++ unterstützt dies nicht für Funktionen mit Ausnahme konst. Sie können basierend auf const überlasten.

Sie können eine Vorlage verwenden, aber dann würden Sie die Template-Parameter angeben müssen, wenn Sie den Anruf zu tätigen.

Legen Sie es in einem anderen Namespace? Das wäre, wie ich es tun würde. Nicht unbedingt eine Überlastung, sondern eine nur mit zwei Methoden mit dem gleichen Namen, aber ein anderer Rahmen (daher der :: Bereichsauflösungsoperator).

So stringnamespace :: mul und intnamespace :: mul. Vielleicht ist es nicht wirklich, was Sie fordern, aber es scheint, wie der einzige Weg, es zu tun.

Sie könnten wie etwas tun

template<typename T>
T mul(int i,int j){
    return i * j;
}

template<>
std::string mul(int i,int j){
    return std::string(j,i);
}

Und dann nennen Sie es wie folgt aus:

int x = mul<int>(2,3);
std::string s = mul<std::string>(2,3);

Es gibt keine Möglichkeit, auf dem Rückgabewert von Überlastung.

OK Sie Genies;) das ist, wie Sie es wie ein Profi tun

.

class mul
{
 int m_i,m_j;
public:
 mull(int i,int j):m_i(i),m_j(j){}
 template
 operator R() 
 {
  return (R)m_i * m_j;
 }
};

verwenden wie


double d = mul(1,2);
long l = mul(1,2);

nicht dumm <>

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top