Encontré la siguiente firma de función y me preguntaba si esto (los puntos suspensivos o "..."
) es algún tipo de polimorfismo?
#include <fcntl.h>
int fcntl(int fd, int cmd, ... );
Gracias por adelantado.
Anónimo
Encontré la siguiente firma de función y me preguntaba si esto (los puntos suspensivos o "..."
) es algún tipo de polimorfismo?
#include <fcntl.h>
int fcntl(int fd, int cmd, ... );
Gracias por adelantado.
Eso es un función variádica. Ver stdarg.h para más detalles.
los ...
significa que puede pasar cualquier número de argumentos a esta función, como ya han mencionado otros comentaristas. Dado que los argumentos opcionales no se escriben, el compilador no puede verificar los tipos y técnicamente puede pasar cualquier argumento de cualquier tipo.
Entonces, ¿esto significa que puede usar esto para implementar algún tipo de función polimórfica? (Es decir, una función que realiza alguna operación basada en el tipo de sus argumentos).
No.
La razón por la que no puede hacer esto es porque no puede inspeccionar en tiempo de ejecución los tipos de argumentos pasados. Se espera que la función que lee en la lista de argumentos variables ya conozca los tipos de argumentos opcionales que va a recibir.
En el caso de una función que realmente se supone que puede tomar cualquier número de argumentos de cualquier tipo (es decir, printf
), los tipos de los argumentos se pasan a través de la cadena de formato. Esto significa que la persona que llama tiene que especificar los tipos que va a pasar en cada invocación, eliminando el beneficio de las funciones polimórficas (que la persona que llama tampoco tiene que conocer los tipos).
Comparar:
// Ideal invocation
x = multiply(number_a, number_b)
y = multiply(matrix_a, matrix_b)
// Standard C invocation
x = multiply_number(number_a, number_b)
y = multiply_matrix(matrix_a, matrix_b)
// Simulated "polymorphism" with varargs
x = multiply(T_NUMBER, number_a, number_b)
y = multiply(T_MATRIX, matrix_a, matrix_b)
Debe especificar el tipo antes de que la función varargs pueda hacer lo correcto, por lo que esto no le aporta nada.
Lasse V. Karlsen
No, esa es la “puntos suspensivos” que está viendo allí, suponiendo que se esté refiriendo a la ...
parte de la declaración.
Básicamente dice que esta función toma un número desconocido de argumentos después de los dos primeros que se especifican allí.
La función debe escribirse de tal manera que sepa qué esperar, de lo contrario, se producirán resultados extraños.
Para otras funciones que soportan esto, mire el printf
función y sus variantes.
DFA
¿C admite polimorfismo? No, no lo hace.
Sin embargo, hay varias bibliotecas, como Python C API, que implementa una variante aproximada de polimorfismo utilizando estructuras y punteros. Tenga en cuenta que el compilador no puede realizar la comprobación de tipos adecuada en la mayoría de los casos.
La técnica es simple:
typedef struct {
char * (*to_string)();
} Type;
#define OBJ_HEADER Type *ob_type
typedef struct {
OBJ_HEADER;
} Object;
typedef struct {
OBJ_HEADER;
long ival;
} Integer;
typedef struct {
OBJ_HEADER;
char *name;
char *surname;
} Person;
Entero y Persona obtienen un objeto Tipo con punteros de función apropiados (por ejemplo, a funciones como entero_a_cadena y persona_a_cadena).
Ahora simplemente declare una función que acepte un Objeto *:
void print(Object *obj) {
printf("%s", obj->type->to_string());
}
ahora puede llamar a esta función tanto con un número entero como con una persona:
Integer *i = make_int(10);
print((Object *) i);
Person *p = make_person("dfa");
print((Object *) p);
EDITAR
alternativamente, puede declarar i y p como Object *; por supuesto, make_int y make_person asignarán espacio para Integer y Person y realizarán la conversión adecuada:
Object *
make_integer(long i) {
Integer *ob = malloc(sizeof(Integer));
ob->ob_type = &integer_type;
ob->ival = i;
return (Object *) ob;
}
NB: No puedo compilar estos ejemplos en este momento, verifíquelos dos veces.
Encontré la siguiente firma de función y me preguntaba si esto (los puntos suspensivos o “…”) es algún tipo de polimorfismo.
si, es un forma primitiva de polimorfismo. Con solo una firma de función, puede pasar varias estructuras. Sin embargo, el compilador no puede ayudarlo a detectar errores de tipo.
tu funcion print
necesita aceptar un argumento de tipo void*
y luego necesitas lanzarlo explícitamente a Object*
para que tu ejemplo funcione.
– Konrad Rodolfo
14 de julio de 2009 a las 10:04
-1 porque creo que no se trata realmente de la pregunta original, a pesar de la palabra “polimorfismo” en el título. Esta respuesta sería más apropiada para una pregunta: ¿cómo podemos implementar el polimorfismo en C.
– John Saunders
14 de julio de 2009 a las 11:05
Konrad Rodolfo
Agregando a lo que se ha dicho: C admite el polimorfismo a través de otros medios. Por ejemplo, tome la biblioteca estándar qsort
función que ordena datos de tipo arbitrario.
Es capaz de hacerlo por medio de untyped (void
) punteros a los datos. También necesita saber el tamaño de los datos para ordenar (proporcionado a través de sizeof
) y la lógica que compara el orden de los objetos. Esto se logra pasando un puntero de función al qsort
función.
Este es un excelente ejemplo de polimorfismo en tiempo de ejecución.
Hay otras formas de implementar el comportamiento orientado a objetos (en particular, llamadas a funciones virtuales) administrando las tablas de funciones virtuales manualmente. Esto se puede hacer almacenando punteros de función en estructuras y pasándolos. Muchas API lo hacen, por ejemplo, WinAPI, que incluso utiliza aspectos avanzados de orientación a objetos, por ejemplo, envío de llamadas de clase base (DefWindowProc
para simular llamar al método virtual de la clase base).
tu funcion print
necesita aceptar un argumento de tipo void*
y luego necesitas lanzarlo explícitamente a Object*
para que tu ejemplo funcione.
– Konrad Rodolfo
14 de julio de 2009 a las 10:04
-1 porque creo que no se trata realmente de la pregunta original, a pesar de la palabra “polimorfismo” en el título. Esta respuesta sería más apropiada para una pregunta: ¿cómo podemos implementar el polimorfismo en C.
– John Saunders
14 de julio de 2009 a las 11:05
Supongo que te refieres a los puntos suspensivos (…)? Si es así, esto indica que seguirán 0 o más parámetros. Se llama varargs, definido en stdarg.h
http://msdn.microsoft.com/en-us/library/kb57fad8.aspx
printf usa esta funcionalidad. Sin él, no podría seguir agregando parámetros al final de la función.
Sugeriría eliminar el sufijo “(VS.71)” de la URL, para que siempre se vincule a la última versión de la documentación.
– Hosam Ali
14 de julio de 2009 a las 9:28
Pregunta bastante justa. +1. Algunas personas todavía piensan que las preguntas simples no son adecuadas, a pesar de las indicaciones de los poderes fácticos de que lo son.
– pax diablo
14 de julio de 2009 a las 9:12
Sugeriría cambiar el título de la pregunta a “¿Qué son los puntos suspensivos (…) en C?”
– Hosam Ali
14 de julio de 2009 a las 9:26
@Hosam: Sí, no se trata realmente de polimorfismo… Título cambiado.
– Dave Sheroman
14 de julio de 2009 a las 10:05
@Dave Sherohman: Tampoco se trata de puntos suspensivos.
– Anónimo
14 de julio de 2009 a las 10:07
Lo que está claro es que viste los puntos suspensivos y pensaste que significaba polimorfismo. no lo hace Una segunda pregunta podría ser: “Dado que los puntos suspensivos no significan polimorfismo, ¿hay otra forma de obtenerlo?”. Esa sería una pregunta aparte.
– John Saunders
14 de julio de 2009 a las 10:55