Ich habe hier auf SO einige Fragen zu diesem Thema gelesen, die mir noch verwirrend erscheinen. Ich habe gerade angefangen, C ++ zu lernen, und ich habe noch keine Vorlagen oder Operatorüberladung und so weiter studiert.
Jetzt gibt es eine einfache Möglichkeit zur Überlastung
class My {
public:
int get(int);
char get(int);
}
ohne Vorlagen oder seltsames Verhalten? oder sollte ich nur
class My {
public:
int get_int(int);
char get_char(int);
}
?
c++
overloading
Schuh
quelle
quelle
int
Rückgabewert sieht so(int)get(9)
undchar
so aus(char)get(9)
.Antworten:
Nein, gibt es nicht. Sie können Methoden basierend auf dem Rückgabetyp nicht überladen.
Die Überlastungsauflösung berücksichtigt die Funktionssignatur . Eine Funktionssignatur besteht aus:
Und hier ist das Zitat:
1.3.11 Unterschrift
Optionen:
1) Ändern Sie den Methodennamen:
class My { public: int getInt(int); char getChar(int); };
2) out Parameter:
class My { public: void get(int, int&); void get(int, char&); }
3) Vorlagen ... in diesem Fall übertrieben.
quelle
My::get<T>(int)
. Es ist eine gültige Alternative _wenn 1) Sie müssen mit vielen verschiedenen Typen umgehen, alle mit demselben Basiscode (z. B.boost::lexical_cast<T>( someStringValue )
oder Sie müssen in der Lage sein, diese Funktionen aus einer anderen Vorlage aufzurufen (myMy.get<T>( i )
woT
ist ein Argument dieser anderen Vorlage)? Ansonsten, wie Luchian sagt, sind sie übertrieben.my.get(0);
den Compiler aufrufen, können Sie nicht entscheiden, welcher Code ausgeführt werden soll.void foo(int x = 0) {} void foo(double x = 0) {}
sollte nicht erlaubt sein. Dies ist jedoch nicht der Fall. Nur in dem Fall, in dem der Compiler wirklich nicht unterscheiden kann (foo()
), erhalten Sie eine FehlermeldungEs ist möglich, aber ich bin nicht sicher, ob es eine Technik ist, die ich Anfängern empfehlen würde. Wie in anderen Fällen verwenden Sie einen Proxy, wenn die Auswahl der Funktionen von der Verwendung des Rückgabewerts abhängen soll. Definieren Sie zuerst Funktionen wie
getChar
undgetInt
dann ein Generikum,get()
das einen Proxy wie folgt zurückgibt:class Proxy { My const* myOwner; public: Proxy( My const* owner ) : myOwner( owner ) {} operator int() const { return myOwner->getInt(); } operator char() const { return myOwner->getChar(); } };
Erweitern Sie es auf so viele Typen, wie Sie benötigen.
quelle
std::string
und der Proxy nur bietetoperator char const*()
, wird es nicht funktionieren.Nein, Sie können nicht nach Rückgabetyp überladen. Nur nach Parametertypen und const / volatile-Qualifizierern.
Eine Alternative wäre, mit einem Referenzargument "zurückzukehren":
void get(int, int&); void get(int, char&);
obwohl ich wahrscheinlich entweder eine Vorlage oder anders benannte Funktionen wie Ihr zweites Beispiel verwenden würde.
quelle
int
Fehlercode ist.Sie können so denken:
Du hast:
int get(int); char get(int);
Es ist nicht zwingend erforderlich, den Rückgabewert der Funktion beim Aufrufen zu erfassen.
Jetzt rufst du an
get(10); -> there is an ambiguity here which function to invoke.
Keine Bedeutung, wenn eine Überladung basierend auf dem Rückgabetyp zulässig ist.
quelle
Wiederbelebung eines alten Threads, aber ich kann sehen, dass niemand die Überladung durch Ref-Qualifier erwähnte. Ref-Qualifizierer sind eine Sprachfunktion, die in C ++ 11 hinzugefügt wurde, und ich bin erst kürzlich darauf gestoßen - sie ist nicht so weit verbreitet wie z. B. Lebenslaufqualifizierer. Die Hauptidee besteht darin, zwischen den beiden Fällen zu unterscheiden: Wenn die Elementfunktion für ein rvalue-Objekt aufgerufen wird und wenn sie für ein lvalue-Objekt aufgerufen wird. Sie können im Grunde so etwas schreiben (ich ändere den OP-Code leicht):
#include <stdio.h> class My { public: int get(int) & { // notice & printf("returning int..\n"); return 42; } char get(int) && { // notice && printf("returning char..\n"); return 'x'; }; }; int main() { My oh_my; oh_my.get(13); // 'oh_my' is an lvalue My().get(13); // 'My()' is a temporary, i.e. an rvalue }
Dieser Code erzeugt die folgende Ausgabe:
returning int.. returning char..
Natürlich könnten, wie es bei Lebenslaufqualifizierern der Fall ist, beide Funktionen den gleichen Typ zurückgegeben haben, und eine Überladung wäre immer noch erfolgreich.
quelle
Während die meisten anderen Kommentare zu diesem Problem technisch korrekt sind, können Sie den Rückgabewert effektiv überladen, wenn Sie ihn mit dem Überladen von Eingabeparametern kombinieren. Zum Beispiel:
class My { public: int get(int); char get(unsigned int); };
DEMO:
#include <stdio.h> class My { public: int get( int x) { return 'I'; }; char get(unsinged int x) { return 'C'; }; }; int main() { int i; My test; printf( "%c\n", test.get( i) ); printf( "%c\n", test.get((unsigned int) i) ); }
Das Ergebnis davon ist:
quelle
In C ++ gibt es keine Möglichkeit, den Rückgabetyp zu überladen. Ohne Vorlagen zu verwenden, ist
get_int
undget_char
das Beste, was Sie tun können.quelle
template <class T> T get(int)
würde funktionieren?get<int>
oder bezeichnenget<char>
, was Sie nicht wirklich überzeugtget_int
undget_char
wenn Sie nicht auch andere Vorlagenfunktionen verwenden.T
ob Sie so etwas habenT get(T)
. Wenn Sie aufrufenget('a')
, leitet der Compiler ab, dass dies einT
ist,char
und Sie müssen nicht explizit aufrufenget<char>('a')
. Ich bin mir immer noch nicht sicher, ob dies Standard ist, obwohl ich denke, dass dies der Fall ist. Zu Ihrer Information, sowohl GCC als auch Clang unterstützen dies.T
überall sonst ein, einschließlich des Rückgabetyps. Ich habe erwartet, dass SieT
in Niklas 'erstem Kommentar ein Beispiel für den Compiler geben, der für die Funktion abgeleitet wurde.Sie können Methoden, die auf Rückgabetypen basieren, nicht überladen. Am besten erstellen Sie zwei Funktionen mit leicht unterschiedlicher Syntax, z. B. in Ihrem zweiten Codefragment.
quelle
Wie bereits erwähnt, sind Vorlagen in diesem Fall übertrieben, aber es ist immer noch eine erwähnenswerte Option.
class My { public: template<typename T> T get(int); }; template<> int My::get<int>(int); template<> char My::get<char>(int);
quelle
Sie können eine Funktion basierend auf dem Rückgabetyp der Funktion nicht überladen. Sie können basierend auf dem Typ und der Anzahl der Argumente, die diese Funktion verwendet, überlagern.
quelle
Ich habe James Kanzes Antwort mit einem Proxy verwendet:
https://stackoverflow.com/a/9569120/262458
Ich wollte vermeiden, viele hässliche static_casts für eine Leere * zu verwenden, also habe ich Folgendes getan:
#include <SDL_joystick.h> #include <SDL_gamecontroller.h> struct JoyDev { private: union { SDL_GameController* dev_gc = nullptr; SDL_Joystick* dev_js; }; public: operator SDL_GameController*&() { return dev_gc; } operator SDL_Joystick*&() { return dev_js; } SDL_GameController*& operator=(SDL_GameController* p) { dev_gc = p; return dev_gc; } SDL_Joystick*& operator=(SDL_Joystick* p) { dev_js = p; return dev_js; } }; struct JoyState { public: JoyDev dev; }; int main(int argc, char** argv) { JoyState js; js.dev = SDL_JoystickOpen(0); js.dev = SDL_GameControllerOpen(0); SDL_GameControllerRumble(js.dev, 0xFFFF, 0xFFFF, 300); return 0; }
Funktioniert perfekt!
quelle