2010-06-11 15 views
40

Ho una classe super come questo:Evitare di avvertimento 'parametro formale Unreferenced'

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

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

..e una sotto-classe come questa:

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

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

Quando compilo la sottoclasse. file cpp, viene visualizzato questo errore

warning C4100: 'param' : unreferenced formal parameter 

Come pratica, venivano utilizzati gli avvertimenti come errori. Come evitare l'avvertimento sopra?

Grazie.

+0

Usa boost :: ignore_unused (param) http://stackoverflow.com/a/24310846/888576 –

risposta

71

In C++ non si deve dare un parametro che non si utilizza un nome in modo da poter solo fare questo:

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

Si potrebbe desiderare di mantenere il nome del parametro nella dichiarazione del file di intestazione per mezzo di documentazione, però. Anche l'istruzione vuota (;) non è necessaria.

+1

@ Charles..Se la funzione è in linea, è legale farlo in questo modo? 'classe Child: public Parent {public: void Function (int/* param */= 0, int param2 = 0) {std :: cout << param2 << std :: endl; }}; ' – bdhar

+0

Si intende un parametro senza nome con un valore predefinito. Non sono sicuro al 100%, ma penso che sia legale. Non conosco alcuna ragione per cui non in ogni caso. –

+3

@bdhar: si noti che è pericoloso fornire parametri predefiniti a diversi livelli della gerarchia, a meno che i valori predefiniti non coincidano. Il problema che si può ottenere è che chiamare la stessa funzione da due contesti potrebbe terminare chiamando lo stesso overrider finale con diversi valori di default: 'struct base {virtual void f (int i = 0); }; struct derived: base {virtual void f (int i = 5); }; int main() {derivato d; base & b = d; d.f()/* D :: f (5) * /; b.f();/* D :: f (0) * /} ' –

17

Un'altra tecnica che è possibile utilizzare se si desidera mantenere il nome del parametro è quello di lanciare a decadere:

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

Questo va bene per i tipi built-in come int, ma se il parametro è un riferimento a un tipo incompleto, convertendolo a void si introduce la necessità per la definizione completa del tipo da vedere dove prima non esisteva tale necessità. – TheBeardyMan

+0

Questa è la soluzione per il linguaggio C, così utile. – Bentoy13

+1

Qt's Q_UNUSED macro è una versione leggermente più elaborata di questo. –

8

Come accennato @Charles Bailey, si può saltare il nome del parametro.

Tuttavia, in alcuni scenari, è necessario il nome del parametro, poiché in build di debug si sta chiamando un ASSERT() su di esso, ma su build retail è un nop. Per questi scenari c'è un macro a portata di mano (almeno in VC++ :-)) UNREFERENCED_PARAMETER(), che è definita come questo:

#define UNREFERENCED_PARAMETER(x) x 

Nota che il semplice getto @R Samuel Klatchko pubblicato anche funziona, ma che personalmente trovo più leggibile se il codice è esplicito che si tratta di un parametro non referenziato rispetto a cast semplice non spiegato come quello.

+1

Nascondere dietro una macro è una buona idea (hai ragione che è più chiaro del mio esempio). Detto questo, dovresti probabilmente aggiungere il cast alla tua macro o potresti ricevere un avvertimento (su g ++ 4.2.1, ricevo 'warning: l'istruzione non ha alcun effetto ') –

+0

Puoi definire ASSERT (param) per build non di debug con (void) param. Il tuo UNREFERENCED_PARAMETER suggerisce che non è affatto referenziato. Ma può essere referenziato - in ASSERT. – harper

26

Preferisco utilizzare una macro, in quanto indica non solo al compilatore la mia intenzione, ma altri manutentori del codice, ed è ricercabile in seguito.

Il metodo di commentare il nome dell'argomento può essere facilmente ignorato da persone che non conoscono il codice (o me 6 mesi dopo).

Tuttavia, si tratta di un problema di stile, nessuno dei due metodi è "migliore" o più ottimale per quanto riguarda il codice generato, le prestazioni o la robustezza. Per me, il fattore decisivo è informare gli altri del mio intento attraverso un sistema standardizzato. Omettendo il nome del parametro e mettere in un commento funzionerebbe altrettanto bene:

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

alternativa:

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

direi che la soluzione peggiore è sopprimere il messaggio di avviso; che ciò influirà sul tuo intero file o progetto e perderai la consapevolezza che forse ti sei perso qualcosa. Almeno aggiungendo la macro, o commentando il nome dell'argomento, hai detto ad altri che hai preso una decisione consapevole di non usare questo argomento e che non è un errore.

Windows SDK in WinNT.h definisce UNREFERENCED_PARAMETER() insieme a DBG_UNREFERENCED_PARAMETER() e DBG_UNREFERENCED_LOCAL_VARIABLE(). Valutano tutti la stessa cosa, ma la differenza è che DBG_UNREFERENCED_PARAMETER() viene utilizzato quando si avvia e si prevede di utilizzare il parametro quando il codice è più completo. Quando sei sicuro di non utilizzare mai il parametro, utilizza la versione UNREFERENCED_PARAMETER().

Microsoft Foundation Classes (MFC) ha una convenzione simile, con i più corti UNUSED() e UNUSED_ALWAYS() macro.

Scegli uno stile e bastone con esso. In questo modo più avanti puoi cercare "DBG_UNREFERENCED_PARAMETER" nel tuo codice e trovare le istanze di dove ti aspettavi di usare un argomento, ma non l'hai fatto. Adottando uno stile coerente e usandolo abitualmente, lo renderete più facile per gli altri e voi stessi in seguito.

+1

Commentare il nome del parametro è sicuramente la migliore pratica a mio avviso, e anche la più leggibile. –

+1

@DavidKirby non puoi farci un nome commentato se hai ifdef all'interno della funzione che rende il parametro usato o meno a seconda della definizione. –

+1

Il parametro commentato dovrebbe essere NMHDR */* pNMHDR */non NMHDR/* * pNMHDR */come sopra, che è un bug che modifica la firma della funzione. Più in generale, non inserire uno spazio tra il tipo e la stella: NMHDR * pNMHDR –

4

vorrei usare una macro per sopprimere il richiamo formale non referenziato parametro:

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

Questo ha i seguenti vantaggi:

  • differenza #define non utilizzata (x) (void) x, esso doesn Introdurre la necessità di vedere la definizione completa del tipo di parametro laddove prima non esistesse tale necessità.
  • A differenza di #define UNUSED (x) & x, può essere utilizzato tranquillamente con parametri i cui tipi sovraccaricano l'operatore unario &.
2

Pragma funziona bene anche perché è chiaro che stai usando VS. Questo avviso ha un rapporto rumore/beneficio molto elevato, dato che i parametri non referenziati sono molto comuni nelle interfacce di callback e nei metodi derivati. Anche le squadre all'interno di Microsoft Windows che utilizzano W4 sono diventati stanchi della sua inutilità (sarebbe più adatto a/parete) e semplicemente aggiunto al loro progetto:

#pragma warning(disable: 4100) 

Se si vuole alleggerire l'avviso solo per un blocco di codice , circondarlo con:

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

la pratica di lasciare fuori il nome del parametro è il rovescio della medaglia nel debugger che non si può facilmente controllare in base al nome, né aggiungerlo orologio (si confonde se si dispone di più di una parametro non referenziato) e mentre una particolare implementazione di un metodo non può utilizzare il parametro, conoscerne il valore può aiutarti a capire fase di un processo in cui ti trovi, specialmente quando non hai l'intero stack di chiamate sopra di te.

Problemi correlati