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?

¿Fue útil?

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 () y copy () . 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 palabra    void 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?

C11 N1570 borrador estándar

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top