Leí algunas preguntas aquí sobre SO sobre este tema que me parece confuso. Recién comencé a aprender C ++ y aún no he estudiado las plantillas o la sobrecarga de operadores y demás.
Ahora, ¿hay una forma sencilla de sobrecargar
class My {
public:
int get(int);
char get(int);
}
sin plantillas o comportamiento extraño? o debería simplemente
class My {
public:
int get_int(int);
char get_char(int);
}
?
c++
overloading
Zapato
fuente
fuente
int
valor de retorno se verá así(int)get(9)
y conchar
esto(char)get(9)
.Respuestas:
No, no lo hay. No puede sobrecargar métodos basados en el tipo de retorno.
La resolución de sobrecarga tiene en cuenta la firma de la función . Una firma de función se compone de:
Y aquí está la cita:
1.3.11 firma
Opciones:
1) cambie el nombre del método:
class My { public: int getInt(int); char getChar(int); };
2) parámetro de salida:
class My { public: void get(int, int&); void get(int, char&); }
3) plantillas ... exagerado en este caso.
fuente
My::get<T>(int)
. Es una alternativa válida _ si 1) tienes que manejar muchos tipos diferentes, todos con el mismo código básico (por ejemploboost::lexical_cast<T>( someStringValue )
, o tienes que poder llamar a estas funciones desde alguna otra plantilla (myMy.get<T>( i )
, dondeT
hay un argumento de esta otra plantilla . De lo contrario, como dice Luchian, son exagerados.my.get(0);
al compilador, no tendría forma de decidir qué pieza de código ejecutar.void foo(int x = 0) {} void foo(double x = 0) {}
debería ser rechazado. Sin embargo, no lo es. Solo en el caso de que el compilador realmente no pueda distinguir (foo()
) obtendrá un errorEs posible, pero no estoy seguro de que sea una técnica que recomendaría a los principiantes. Como en otros casos, cuando desea que la elección de funciones dependa de cómo se usa el valor de retorno, usa un proxy; primero defina funciones como
getChar
ygetInt
, luego un genéricoget()
que devuelve un Proxy como este:class Proxy { My const* myOwner; public: Proxy( My const* owner ) : myOwner( owner ) {} operator int() const { return myOwner->getInt(); } operator char() const { return myOwner->getChar(); } };
Extiéndalo a tantos tipos como necesite.
fuente
std::string
, y el proxy solo lo ofreceoperator char const*()
, no funcionará.No, no puede sobrecargar por tipo de retorno; solo por tipos de parámetros y calificadores const / volatile.
Una alternativa sería "regresar" usando un argumento de referencia:
void get(int, int&); void get(int, char&);
aunque probablemente usaría una plantilla o funciones con nombres diferentes como su segundo ejemplo.
fuente
int
código de error.Puedes pensar de esta manera:
Tienes:
int get(int); char get(int);
Y no es obligatorio recopilar el valor de retorno de la función al invocar.
Ahora, invocas
get(10); -> there is an ambiguity here which function to invoke.
Por lo tanto, no tiene sentido si se permite la sobrecarga según el tipo de retorno.
fuente
Resucitando un hilo antiguo, pero puedo ver que nadie mencionó la sobrecarga de los calificadores de referencia. Los calificadores de referencia son una característica del lenguaje agregada en C ++ 11 y recientemente me encontré con ella; no está tan extendida como, por ejemplo, los calificadores de cv. La idea principal es distinguir entre los dos casos: cuando la función miembro se llama en un objeto rvalue y cuando se llama en un objeto lvalue. Básicamente, puedes escribir algo como esto (estoy modificando ligeramente el código de OP):
#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 }
Este código producirá el siguiente resultado:
returning int.. returning char..
Por supuesto, como es el caso de los calificadores cv, ambas funciones podrían haber devuelto el mismo tipo y la sobrecarga aún sería exitosa.
fuente
Como se dijo antes, las plantillas son exageradas en este caso, pero sigue siendo una opción que vale la pena mencionar.
class My { public: template<typename T> T get(int); }; template<> int My::get<int>(int); template<> char My::get<char>(int);
fuente
Si bien la mayoría de los otros comentarios sobre este problema son técnicamente correctos, puede sobrecargar efectivamente el valor de retorno si lo combina con el parámetro de entrada de sobrecarga. Por ejemplo:
class My { public: int get(int); char get(unsigned int); };
MANIFESTACIÓN:
#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) ); }
El resultado de esto es:
fuente
No hay forma de sobrecargar por tipo de retorno en C ++. Sin usar plantillas, usar
get_int
yget_char
será lo mejor que pueda hacer.fuente
template <class T> T get(int)
funcionaría?get<int>
oget<char>
, lo que realmente no te hace ganar muchoget_int
yget_char
si no estás usando también otras funciones de plantilla.T
si tiene algo comoT get(T)
. Si llamaget('a')
, el compilador deduce queT
es unchar
y no tiene que llamar explícitamenteget<char>('a')
. Todavía no estoy seguro de si esto es estándar, aunque creo que lo es. Para su información, tanto GCC como Clang lo admiten.T
cualquier otro lugar, incluido el tipo de retorno. Esperaba que dieras un ejemplo del compilador deduciendoT
de la función en el primer comentario de Niklas.No puede sobrecargar métodos basados en tipos de devolución. Su mejor opción es crear dos funciones con una sintaxis ligeramente diferente, como en su segundo fragmento de código.
fuente
no se puede sobrecargar una función en función del tipo de retorno de la función. puede sobrepasar según el tipo y la cantidad de argumentos que toma esta función.
fuente
Usé la respuesta de James Kanze usando un proxy:
https://stackoverflow.com/a/9569120/262458
Quería evitar usar muchos static_casts feos en un void *, así que hice esto:
#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; }
¡Funciona perfectamente!
fuente