2010-06-11 6 views
40

Ich habe eine Super-Klasse wie folgt aus:Vermeiden 'Unreferenzierte Formale Parameter' Warnung

class Parent 
{ 
public: 
    virtual void Function(int param); 
}; 

void Parent::Function(int param) 
{ 
    std::cout << param << std::endl; 
} 

eine Unterklasse wie folgt ..und:

class Child : public Parent 
{ 
public: 
    void Function(int param); 
}; 

void Child::Function(int param) 
{ 
    ;//Do nothing 
} 

Wenn ich die Unterklasse kompilieren. cpp-Datei, bekomme ich diesen Fehler

Als eine Praxis haben wir verwendet, um Warnungen als Fehler zu behandeln. Wie vermeide ich die obige Warnung?

Danke.

+0

Verwenden Sie boost :: ignore_unused (param) http://Stackoverflow.com/a/24310846/888576 –

Antwort

71

In C++ müssen Sie einen Parameter nicht geben, dass Sie keinen Namen verwenden, so dass Sie dies nur tun können:

void Child::Function(int) 
{ 
    //Do nothing 
} 

Sie können in der den Parameternamen in der Deklaration behalten möchten Header-Datei über die Dokumentation, obwohl. Die leere Anweisung (;) ist ebenfalls nicht erforderlich.

+1

@ Charles..Wenn die Funktion inline ist, ist es legal, so zu tun? 'class Kind: public Parent {public: void Funktion (int/* param */= 0, int param2 = 0) {std :: cout << param2 << std :: endl; }}; ' – bdhar

+0

Sie meinen, einen namenlosen Parameter mit einem Standardwert zu haben. Ich bin mir nicht 100% sicher, aber ich denke, dass es legal ist. Ich weiß aus keinem Grund, warum nicht auf jeden Fall. –

+3

@bdhar: Beachten Sie, dass es gefährlich ist, Standardparameter auf verschiedenen Ebenen der Hierarchie anzugeben, sofern Ihre Standardwerte nicht übereinstimmen. Das Problem, das Sie bekommen können, ist, dass das Aufrufen der gleichen Funktion aus zwei Kontexten den gleichen finalen Overrider mit unterschiedlichen Standardwerten aufrufen könnte: 'struct base {virtual void f (int i = 0); }; struct abgeleitet: basis {virtuelles void f (int i = 5); }; int main() {abgeleiteter d; Basis & b = d; d.f()/* D :: f (5) * /; b.f();/* D :: f (0) * /} ' –

17

Eine andere Technik, die Sie verwenden können, wenn Sie den Parameternamen behalten wollen, ist nichtig zu werfen:

void Child::Function(int param) 
{ 
    (void)param; //Do nothing 
} 
+0

Das ist für integrierte Typen wie int OK, aber wenn der Parameter eine Referenz auf einen unvollständigen Typ ist, führt die Umwandlung in void dazu, dass die vollständige Definition des Typs angezeigt wird, der zuvor noch nicht vorhanden war. – TheBeardyMan

+0

Dies ist die Lösung für die C-Sprache, also nützlich. – Bentoy13

+1

Das Q_UNUSED-Makro von Qt ist eine etwas schickere Version davon. –

8

Als @Charles Bailey erwähnt, können Sie den Parameternamen auslassen.

In bestimmten Szenarios benötigen Sie jedoch den Parameternamen, da Sie in Debugbuilds ASSERT() darauf aufrufen, aber auf Einzelhandelsbuilds ist es ein nop. Für diese Szenarien gibt es eine handliche Makros (zumindest in VC++ :-)) UNREFERENCED_PARAMETER(), die wie folgt definiert ist:

#define UNREFERENCED_PARAMETER(x) x 

Beachten Sie, dass die einfache Guss @R Samuel Klatchko auch Werke geschrieben, aber ich finde es persönlich mehr lesbar, wenn der Code explizit besagt, dass es sich um einen nicht referenzierten Parameter handelt und nicht um einen einfachen, nicht erklärten Cast.

+1

Es ist eine gute Idee, sich hinter einem Makro zu verstecken (Sie haben Recht, es ist klarer als mein Beispiel). Das heißt, Sie sollten wahrscheinlich die Besetzung zu Ihrem Makro hinzufügen, oder Sie erhalten eine Warnung (auf g ++ 4.2.1, bekomme ich 'Warnung: Anweisung hat keinen Effekt') –

+0

Sie könnten ASSERT (Param) für Nicht-Debug-Build mit definieren (ungültig) param. Ihr UNREFERENCED_PARAMETER schlägt vor, dass überhaupt nicht darauf verwiesen wird. Aber es kann referenziert werden - in ASSERT. – harper

26

Ich bevorzuge mit einem Makro, da es nicht nur den Compiler meine Absicht, sondern auch andere Betreuer des Codes, und es ist später suchbar.

Die Methode zum Auskommentieren des Argumentnamens kann leicht von Personen übersehen werden, die mit dem Code nicht vertraut sind (oder mich 6 Monate später).

Es ist jedoch ein Stil-Problem, beide Methoden sind "besser" oder besser in Bezug auf Code-Generierung, Leistung oder Robustheit. Entscheidend ist für mich, dass ich über ein standardisiertes System andere über meine Absichten informiert. Das Weglassen der Parameternamen und in einem Kommentar setzen würde gleich gut funktionieren:

void CFooBar::OnLvnItemchanged(NMHDR *pNMHDR, LRESULT *pResult) 
{ 
    UNREFERENCED_PARAMETER(pNMHDR); 

Alternativ:

void CFooBar::OnLvnItemchanged(NMHDR* /* pNMHDR */, LRESULT *pResult) 
{ 
    // Not using: pNMHDR 

Ich würde sagen, dass die schlechteste Lösung, die Warnmeldung zu unterdrücken; Das wirkt sich auf Ihre gesamte Datei oder Ihr Projekt aus und Sie werden das Wissen verlieren, dass Sie etwas übersehen haben. Zumindest durch Hinzufügen des Makros oder Auskommentieren des Argumentnamens haben Sie anderen gesagt, dass Sie sich bewusst dafür entschieden haben, dieses Argument nicht zu verwenden, und dass es kein Fehler ist.

Das Windows SDK in WinNT.h definiert UNREFERENCED_PARAMETER() zusammen mit DBG_UNREFERENCED_PARAMETER() und DBG_UNREFERENCED_LOCAL_VARIABLE(). Sie alle bewerten dasselbe, aber der Unterschied besteht darin, dass DBG_UNREFERENCED_PARAMETER() verwendet wird, wenn Sie beginnen und den Parameter zu verwenden, wenn der Code vollständiger ist. Wenn Sie sicher sind, dass Sie den Parameter nie verwenden werden, verwenden Sie die UNREFERENCED_PARAMETER() - Version.

Die Microsoft Foundation Classes (MFC) haben eine ähnliche Konvention mit den kürzeren UNUSED() und UNUSED_ALWAYS() Makros.

Wählen Sie einen Stil und bleiben Sie dabei. Auf diese Weise können Sie später in Ihrem Code nach "DBG_UNREFERENCED_PARAMETER" suchen und nach Instanzen suchen, bei denen Sie ein Argument verwenden wollten, dies aber nicht taten. Indem Sie einen konsistenten Stil verwenden und ihn regelmäßig verwenden, erleichtern Sie es später für sich und andere.

+1

Kommentar der Parametername ist definitiv die beste Praxis meiner Meinung nach, und auch die am besten lesbar. –

+1

@DavidKirby Sie können uns keinen auskommentierten Namen geben, wenn Sie ifdef innerhalb der Funktion haben, die je nach Definition den Parameter verwendet oder nicht. –

+1

Der auskommentierte Parameter sollte NMHDR */* pNMHDR */nicht NMHDR/* * pNMHDR */wie oben sein, was ein Fehler ist, der die Funktionssignatur ändert. Ganz allgemein, legen Sie kein Leerzeichen zwischen dem Typ und dem Stern: NMHDR * pNMHDR –

4

ich einen Makro verwenden würde das nicht referenzierte formalen Parameter zur Unterdrückung dieser Warnung:

#define UNUSED(x) (&reinterpret_cast< const int& >(x)) 

Dies hat folgende Vorteile:

  • Im Gegensatz zu #define UNUSED (x) (void) x, es doesn Es muss kein Bedarf für die vollständige Definition des Typs des Parameters bestehen, der gesehen werden muss, wenn zuvor kein solcher Bedarf bestand.
  • Im Gegensatz zu #define UNUSED (x) & x kann es sicher mit Parametern verwendet werden, deren Typen den unären & Operator überlasten.
2

Pragma funktioniert auch gut, weil es klar ist, dass Sie VS verwenden. Diese Warnung hat ein sehr hohes Rausch-Nutzen-Verhältnis, da nicht referenzierte Parameter in Callback-Interfaces und abgeleiteten Methoden sehr häufig vorkommen. Auch Teams in Microsoft Windows, die W4 seiner Sinnlosigkeit müde geworden verwenden (wäre besser geeignet für/Wand) und einfach zu ihrem Projekt hinzugefügt:

#pragma warning(disable: 4100) 

Wenn Sie die Warnung nur für einen Code-Block lindern wollen , umgeben Sie es mit:

#pragma warning(push) 
#pragma warning(disable: 4100) 
void SomeCallbackOrOverride(int x, float y) { } 
#pragma warning(pop) 

die Praxis der Parametername den Nachteil im Debugger hat, dass man nicht einfach durch Name noch hinzuzufügen, um die Uhr kontrollieren können wegzulassen (verwirrt wird, wenn Sie mehr als einen haben nicht referenzierter Parameter), und während eine bestimmte Implementierung einer Methode den Parameter möglicherweise nicht verwendet, kann die Kenntnis ihres Wertes Ihnen dabei helfen, whi herauszufinden ch stadium eines Prozesses, in dem Sie sich befinden, besonders wenn Sie nicht den gesamten Callstack über Ihnen haben.