2010-02-09 12 views
17

Si no hay sobrecarga de funciones, el nombre de la función sirve como la dirección del código de función, y cuando se llama a una función, su dirección es fácil de encontrar usando su nombre. Sin embargo, con la sobrecarga de funciones, ¿cómo exactamente puede el programa encontrar la dirección de función correcta? ¿Hay una tabla oculta similar a las tablas virtuales que almacena las funciones sobrecargadas con su dirección? ¡Muchas gracias!En C++, ¿cómo se implementa típicamente la sobrecarga de funciones?

+4

Las personas que sugieren el nombre de manipulación están equivocadas, creo. No es como si el compilador destrozara el nombre y solo hiciera una búsqueda entre los nombres destrozados. Necesita inferir los tipos apropiados de los métodos disponibles. Una vez que lo hace, ya sabe a qué método llamar. Luego usa el nombre destrozado como el _último paso. El cambio de nombre no es un requisito previo para determinar qué función sobrecargada llamar. –

+0

¿Tal vez este comentario debería ir en una de las respuestas equivocadas a las que te refieres? – Manuel

+0

Hay demasiados, así que lo dejé aquí. –

Respuesta

11

El compilador puede ver la llamada y hacerla coincidir con las implementaciones sobrecargadas existentes conocidas, y seleccionar la correcta. No hay necesidad de una tabla dinámica, todo es perfectamente factible estáticamente en tiempo de compilación.

Actualización: eliminado mi intento de ilustrar el concepto mostrando las funciones de nombre diferente que el compilador puede elegir.

+0

La gente dice que esta tecniq Name Mangling. Busque esta palabra clave – SunnyShah

+4

El cambio de nombre es solo para diferenciar entre nombres de identificadores, sobrecargados o no. El objetivo principal del cambio de nombre no es atender a la sobrecarga, sino evitar conflictos de nombres. En el caso sobrecargado, el compilador tiene que determinar qué método llamar y ahí es donde está la lógica principal. Creo que el OP quería saber si esto era una cosa de tiempo de compilación/tiempo de ejecución. –

+0

Eso no es exacto, por lo general, el vinculador necesita calcular la dirección de la llamada. La decoración del nombre importa mucho. Sí, existe la posibilidad de omitir la solicitud de enlace si la función se encuentra en la misma unidad de traducción. Si eso realmente sucede es un detalle de implementación. –

0

Es, creo, logrado a través de renombrado de nombres:

las funciones que conoces como foo (int) y foo (doble) son en realidad un nombre como int_foo() y double_foo() (o similar, yo no estoy completamente seguro de la semántica particular empleada para C++). Esto significa que los símbolos de C++ suelen ser un orden de magnitud mayor que los nombres que se les da en el código.

3

Las funciones sobrecargadas se resuelven en tiempo de compilación. El compilador encuentra una coincidencia adecuada para el conjunto de parámetros dado y simplemente llama a la función correspondiente por su dirección (void foo(int) y void foo() son prácticamente dos funciones totalmente independientes; si tiene foo(4) en su código, el compilador sabe a qué función llamar).

5

Si están hablando de métodos sobrecargados de la misma clase, así:

void function(int n); 
void function(char *s); 
... 

objectInstance->function("Hello World") 

Es una cosita tiempo de compilación. El compilador sabe (o en algunas situaciones, adivina mejor) en este punto a qué método llamar.

Un comentario que hice en la pregunta, repito aquí.

Las personas que sugieren el nombre de mangling están equivocadas, creo. No es como si el compilador destrozara el nombre y solo hiciera una búsqueda entre los nombres destrozados. Necesita inferir los tipos apropiados de los métodos disponibles. Una vez que lo hace, ya sabe a qué método llamar. A continuación, utiliza el nombre destrozado como el último paso. El cambio de nombre no es un requisito previo para determinar qué función sobrecargada llamar.

+0

A la persona que dio un -1. Al menos deja un comentario. Puedo eliminar/editar la publicación si la información es incorrecta. ¡Dame la oportunidad de aprender también! –

+0

Supongo que esa persona (no yo) rechazó porque realmente no dio una respuesta clara. En su lugar, solo dice "tiempo de compilación" y "el compilador solo sabe qué hacer", lo que de hecho es un poco inexacto. – AndiDog

+0

Bueno, el cambio de nombre es inexacto, IMO. Lo mejor que podemos decir es que el "compilador sabe". Cada compilador puede tener su propia implementación. –

-1

La firma de función se compone del nombre de función + parámetro (s) tipo (s)

12

Name mangling.

Todo se hace en tiempo de compilación. El compilador de C++ en realidad modifica los nombres de las funciones que le des internamente, de manera que una función como

int foo(int a, float b, char c) 

internamente consigue un nombre equivalente a

func_foo_int_float_char() 

(el símbolo real es generalmente una cierta jerigonza como [email protected]@@[email protected]).

Como puede ver, el nombre se decora según el número exacto y los tipos de parámetros pasados.Entonces, cuando llamas a una función, es fácil para el compilador mirar los parámetros que estás pasando, decorar el nombre de la función con ellos y crear el símbolo correcto. Por ejemplo,

int a, b; float f; char c; 
foo(a,f,c) ; // compiler looks for an internal symbol called func_foo_int_float_char 
foo(a,b,c) ; // compiler looks for a symbol called func_foo_int_int_char 

De nuevo, todo se hace completamente en tiempo de compilación.

+6

Es al revés. El compilador primero mira todos los foos, elige uno que coincide de acuerdo con todas las reglas en el estándar, y luego tal vez emite un nombre destrozado para el enlazador. – UncleBens

+0

Muy informativo, gracias. – Dasaru

-1

Incluso si no hay una sobrecarga de función, los compiladores normalmente modifican la función y los nombres de las variables. Se llama name mangling. Sucede tanto en C como en C++. El nombre de la función puede decorarse notablemente mediante (1) convención de llamadas, (2) función de sobrecarga de C++, (3) función de miembro de clase.

GNU binutil c++filt puede Undecorate este nombre revuelto, y en Windows, hay UnDecorateSymbolName

-1

compiladores de C++ usar el nombre mangling (nombre diferente para cada uno de sobrecarga) para distinguir entre las funciones en el archivo objeto. Por ejemplo

int test(int a){} 
int test(float a,float b){} 
int test(double a){} 
int testbam(double a){} 

produciría los nombres de símbolos __Z4testi, __Z4testff, __Z4testd, __Z7testbamd. Este nombre de manipulación es altamente dependiente del compilador (lamentablemente) y una de las muchas razones por las que a menudo se prefiere C sobre C++.

Al llamar a la función test, el compilador coincide con los tipos de argumento y el número de argumentos dados para cada sobrecarga de función. Los prototipos de funciones se usan para descubrir cuál debería llamarse.

Cuestiones relacionadas