es f (nulo) obsoleto en C y C ++ modernos [duplicado]
-
03-07-2019 - |
Pregunta
Esta pregunta ya tiene una respuesta aquí:
Actualmente estoy refactorizando / ordenando algún código C usado en un proyecto C ++, y veo regularmente funciones como:
int f(void)
que tendería a escribir como:
int f()
¿Hay alguna razón para no reemplazar (vacío) con () en toda la base de código para mejorar la coherencia, o hay una diferencia sutil entre los dos que desconozco? Más específicamente, si una función miembro virtual en C ++ se describe como:
virtual int f(void)
y una clase derivada incluye una función miembro:
<*>¿es esto una anulación válida? Además, ¿es probable que encuentre algún problema de vinculador basado en firmas casi idénticas?
Solución
En C, la declaración int f (void)
significa una función que devuelve int que no toma parámetros. La declaración int f ()
significa una función que devuelve int que toma cualquier número de parámetros. Por lo tanto, si tiene una función que no toma parámetros en C, la primera es el prototipo correcto.
En C ++, creo que int f (void)
está en desuso, y se prefiere int f ()
, ya que específicamente significa una función que no tiene parámetros.
Otros consejos
Para agregar a la respuesta de Chris, usar int f ()
es una mala práctica en C, en mi experiencia, ya que pierde la capacidad del compilador de comparar la declaración de la función con su definición, para asegurarse de que será llamado correctamente.
Por ejemplo, el siguiente código cumple con las normas C:
#include <stdio.h>
void foo();
void bar(void) {
foo();
}
void foo(int a) {
printf("%d\n", a);
}
Pero da como resultado un comportamiento indefinido, ya que a
no se pasó a foo
.
En C ++, hay dos versiones de foo
: una que no toma argumentos y otra que toma un int
. Entonces bar
termina llamando a la versión indefinida, lo que daría como resultado un error de enlazador (suponiendo que no haya otras definiciones de foo
en ninguna parte).
Las respuestas anteriores son bastante correctas, pero estoy enlazando a la excelente página de David Tribble ya que da un excelente explicación sobre este y muchos otros temas.
Lo más destacado:
C distingue entre una función declarado con una lista de parámetros vacía y una función declarada con un lista de parámetros que consta solo de vacío. El primero es un prototipo función que toma un número no especificado de argumentos, mientras que este último es un función prototipo sin tomar argumentos.
C ++, por otro lado, no hace distinción entre los dos declaraciones y los considera a ambos significar una función que no toma argumentos.
Para el código que está destinado a ser compilado como C o C ++, el mejor La solución a este problema es siempre Declarar funciones sin parámetros. con un prototipo vacío explícito.
Los prototipos de funciones vacías son un característica en desuso en C99 (ya que estaban en C89).
Editar: Después de mirar el estándar, quizás valga la pena señalar que la sintaxis de func (void) está no en desuso en C ++, pero comúnmente se considera más un lenguaje de estilo C. Creo que la mayoría de los programadores de C ++ que he encontrado prefieren la lista de parámetros vacía.
Edición 2: Agregar una cita del estándar C ++, sección 8.3.5, párrafo 2:
" Si la cláusula-declaración-parámetro está vacía, la función no acepta argumentos. La lista de parámetros (nula) es equivalente a la lista de parámetros vacía. Excepto en este caso especial, void no será un tipo de parámetro (aunque los tipos derivados de void, como void *, can). & Quot;
No se menciona que ninguno de los formularios está en desuso. Gracias de nuevo a la excelente página web del Sr. Tribble por indicarme la sección correcta de la norma.
tl; dr: use void
.
Dada la compatibilidad con versiones anteriores en C ++ y el poco de ambigüedad que se identifica a continuación, afirmo que volvemos a KnR y ANSI C para obtener una respuesta concluyente:
int getline(void);
int copy(void)
Dado que las versiones especializadas de getline y copy no tienen argumentos, la lógica sugeriría que sus prototipos al principio del archivo debe ser
getline ()
ycopy ()
. Pero por compatibilidad con programas C más antiguos, el estándar toma una lista vacía como un estilo antiguo declaración, y desactiva todas las listas de argumentos la palabravoid
debe usarse para una lista explícitamente vacía. [Kernighan & amp; Richie, el lenguaje de programación C, 1988, páginas 32-33]
y ..
El significado especial de la lista de argumentos vacía tiene la intención de permitir Programas C más antiguos para compilar con nuevos compiladores. Pero es una mala idea Úsalo con nuevos programas. Si la función toma argumentos, declarar. ellos; si no requiere argumentos, use void [ibid, Pg. 73]
EDITAR: Rompe el resto en una discusión separada aquí: ¿Especificar el uso de void en la declaración de una función que no toma argumentos aborda The Most Vexing Parse?
void f ()
está en desuso, se recomienda void f (void)
:
6.11.6 Declaradores de función :
1 El uso de declaradores de función con paréntesis vacíos (no parámetro de formato de prototipo) declaradores de tipo) es una característica obsolescente.
Introducción :
2 Ciertas características son obsoletas, lo que significa que pueden considerarse para retirada en futuras revisiones de esta Norma Internacional. Se conservan porque de su uso generalizado, pero su uso en nuevas implementaciones (para la implementación funciones) o se desaconsejan los nuevos programas (para el lenguaje [6.11] o las funciones de la biblioteca [7.31]).
Discusión detallada: https://stackoverflow.com/a/36292431/895245
C ++ 11 Borrador estándar N3337
Ni void f (void)
ni void f ()
están en desuso.
void f (void)
existe para la compatibilidad con C. Anexo C " Compatibilidad " C.1.7 Cláusula 8: declaradores :
8.3.5 Cambio: en C ++, una función declarada con una lista de parámetros vacía no tiene argumentos. En C, un vacío. lista de parámetros significa que el número y el tipo de los argumentos de la función son desconocidos.
Como void f ()
está en desuso en C y se recomienda void f (void)
, void f (void)
existirá para siempre y cuando C ++ quiera mantener la compatibilidad.
void f (void)
y void f ()
son lo mismo en C ++. Por lo tanto, el void f (void)
más largo solo tiene sentido si le importa escribir código que se compila tanto en C como en C ++, lo que probablemente no valga la pena.
Discusión detallada: https://stackoverflow.com/a/36835303/895245
En C ++, int f (void)
es de hecho una declaración en desuso que es 100% equivalente a int f ()
. Es es la misma firma. El void
en este contexto es tan significativo como p. Ej. espacio en blanco Eso también significa que están sujetos a la Regla de una definición (no se sobrecargan) y Derived :: f (void)
anula Base :: f ()
.
Sin embargo, no te metas con cosas como f (const void)
. No hay mucho consenso sobre qué significa ese tipo de rareza.