Frage

Ich refaktorieren/aufzuräumen Sie einen alten C -Code, der in einem C ++ - Projekt verwendet wird, und sehen regelmäßig Funktionen wie:

int f(void)

was ich neigen würde, als:

int f()

Gibt es einen Grund, (void) durch () in der gesamten Codebasis nicht zu ersetzen, um die Konsistenz zu verbessern, oder gibt es einen subtilen Unterschied zwischen den beiden, die ich nicht bewusst bin? Insbesondere, wenn eine virtuelle Mitgliedsfunktion in C ++ beschrieben wird als:

virtual int f(void)

und eine abgeleitete Klasse enthält eine Mitgliedsfunktion:

int f()

Ist das eine gültige Überschreibung? Stehe ich außerdem auf Linkerprobleme auf basierend auf nahezu identischen Signaturen auf?

War es hilfreich?

Lösung

In C die Erklärung int f(void) bedeutet eine Funktion, die int zurückgibt, die keine Parameter erfordert. Die Erklärung int f() bedeutet eine Funktion, die int zurückgibt, die eine beliebige Anzahl von Parametern erfordert. Wenn Sie also eine Funktion haben, die in C keine Parameter nimmt, ist ersterer der richtige Prototyp.

In C ++ glaube ich int f(void) ist veraltet und int f() wird bevorzugt, wie es ausdrücklich eine Funktion bedeutet, die keine Parameter nimmt.

Andere Tipps

Um Chris 'Antwort hinzuzufügen, verwenden Sie int f() ist nach meiner Erfahrung eine schlechte Praxis in C, da Sie die Fähigkeit des Compilers verlieren, die Erklärung der Funktion mit seiner Definition zu vergleichen, um sicherzustellen, dass sie korrekt aufgerufen wird.

Beispielsweise ist der folgende Code Standards-konforme C:

#include <stdio.h>
void foo();
void bar(void) {
    foo();
}
void foo(int a) {
    printf("%d\n", a);
}

Aber es führt zu undefiniertem Verhalten, da seitdem a wurde nicht an übergeben foo.

In C ++ gibt es zwei Versionen von foo: eine, die keine Argumente nimmt und eine, die eine nimmt int. So bar Aufrufe die undefinierte Version, die zu einem Linkerfehler führen würde (vorausgesetzt, es gibt keine anderen Definitionen von foo irgendwo).

Die obigen Antworten sind recht korrekt, aber ich verlinke mit David Tribbles hervorragende Seite, da es eine gibt Tolle Erklärung In diesem und vielen anderen Themen.

Die Höhepunkte:

C unterscheidet zwischen einer mit einer leeren Parameterliste deklarierten Funktion und einer Funktion, die mit einer Parameterliste deklariert wird, die nur aus Hohlräumen besteht. Ersteres ist eine nicht totypisierte Funktion, die eine nicht spezifizierte Anzahl von Argumenten übernimmt, während letzteres eine prototypisierte Funktion ist, die keine Argumente übernimmt.

C ++ unterscheidet dagegen nicht zwischen den beiden Erklärungen und betrachtet sie als eine Funktion, die keine Argumente nimmt.

Für Code, der als C- oder C ++ kompiliert werden soll, besteht die beste Lösung für dieses Problem darin, immer Funktionen zu deklarieren, die keine Parameter mit einem expliziten Hohlraumprototyp annehmen.

Leere Funktionsprototypen sind ein veraltetes Merkmal in C99 (wie in C89).

Bearbeiten: Nachdem Sie sich den Standard angesehen haben, ist es vielleicht erwähnenswert, dass die Func (void) -Syntax ist nicht In C ++ veraltet, wird aber üblicherweise eher als Idiom im C-Stil berücksichtigt. Ich denke, die meisten C ++ - Programmierer, die ich über die leere Parameterliste befreit habe.

Bearbeiten 2: Hinzufügen eines Zitats aus dem C ++ - Standard, Abschnitt 8.3.5, Absatz 2:

"Wenn die Parameterdeklaration-Klausel leer ist, nimmt die Funktion keine Argumente ein. Die Parameterliste (void) entspricht der leeren Parameterliste. Mit Ausnahme dieses Sonderfall wie void*, Can). "

Es wird nicht erwähnt, dass die beiden Formular veraltet ist. Nochmals vielen Dank an die hervorragende Website von Mr. Tribble, dass Sie mich auf den richtigen Abschnitt des Standards hingewiesen haben.

tl; dr: Verwendung void.

Angesichts der nach hinten nach unten identifizierten Abwehungskompatibilität in C ++ behaupte ich, dass wir bis zu KNR und ANSI C zurückkehren, um eine abschließende Antwort zu erhalten:

int getline(void);
int copy(void)

Da die spezialisierten Versionen von GetLine und Copy keine Argumente haben, schlägt die Logik vor, dass ihre Prototypen zu Beginn der Datei sein sollten getline() und copy(). Für die Kompatibilität mit älteren C-Programmen nimmt der Standard jedoch eine leere Liste als Erklärung im alten Stil und schaltet alle Argumentlistenüberprüfung aus. das Wort void Muss für eine explizit leere Liste verwendet werden. [Kernighan & Richie, The C Programmiersprache, 1988, PGS 32-33

und..

Die besondere Bedeutung der leeren Argumentliste soll älteren C -Programmen mit neuen Compilern ermöglichen. Aber es ist eine schlechte Idee, es mit neuen Programmen zu verwenden. Wenn die Funktion Argumente nimmt, deklarieren Sie sie; Wenn es keine Argumente erfordert, verwenden Sie Leere [ebenda, pg. 73

Bearbeiten: Der Rest hat hier in eine separate Diskussion eingebrochen:Bescheidet die Angabe der Verwendung von Leere in der Erklärung einer Funktion, die keine Argumente annimmt, mit dem ärgerlichsten Analyse?

C11 N1570 Standardentwurf

void f() ist veraltet, void f(void) empfohlen:

6.11.6 Funktionsdeklaratoren:

1 Die Verwendung von Funktionsdeklaratoren mit leeren Klammern (nicht Prototyp-Format-Parametertyp-Deklaratoren) ist eine veraltete Funktion.

Einführung:

2 Bestimmte Merkmale sind veraltet, was bedeutet, dass sie bei zukünftigen Überarbeitungen dieses internationalen Standards für den Rückzug in Betracht gezogen werden können. Sie werden aufgrund ihrer weit verbreiteten Verwendung beibehalten, ihre Verwendung in neuen Implementierungen (für Implementierungsfunktionen) oder neue Programme (für Sprache [6.11] oder Bibliotheksfunktionen [7.31]) jedoch entmutigt.

Detaillierte Diskussion: https://stackoverflow.com/a/36292431/895245

C ++ 11 N3337 Standardentwurf

Weder void f(void) Noch void f() sind veraltet.

void f(void) existiert für die Kompatibilität mit C. Anhang C "Kompatibilität" C.1.7 Klausel 8: Deklaratoren:

8.3.5 Änderung: In C ++ enthält eine mit einer leere Parameterliste deklarierte Funktion keine Argumente. In C bedeutet eine leere Parameterliste, dass die Anzahl und der Typ der Funktionsargumente unbekannt sind.

Seit void f() ist in C und veraltet void f(void) empfohlen, void f(void) wird existieren, solange C ++ die Kompatibilität aufrechterhalten will.

void f(void) und void f() sind in C ++ gleich. Also desto länger void f(void) ist nur sinnvoll, wenn Sie sich beim Schreiben von Code interessieren, der sowohl unter C als auch C ++ kompiliert, was es wahrscheinlich nicht wert ist.

Detaillierte Diskussion: https://stackoverflow.com/a/36835303/895245

In C ++, int f(void) ist in der Tat eine veraltete Erklärung, die zu 100% entspricht int f(). Es ist die gleiche Signatur. Das void In diesem Zusammenhang ist so signifikant wie z. B. z. B. Whitespace. Das bedeutet auch, dass sie der eine Definitionsregel unterliegen (sie überlasten nicht) und Derived::f(void) überschreiben Base::f().

Leg dich nicht mit Sachen an wie f(const void), obwohl. Es gibt nicht viel Konsens, was diese Art von Verrücktheit bedeutet.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top