2010-06-02 10 views
15

Nel seguente esempio:gcc -Wshadow è troppo rigido?

class A 
{ 
    public: 
    int len(); 
    void setLen(int len) { len_ = len; } // warning at this line 
    private: 
    int len_; 
}; 

gcc con emissione -Wshadow un avvertimento:

main.cpp:4: warning: declaration of `len' shadows a member of `this' 

funzione len e intero len sono di tipo diverso. Perché l'avvertimento?

Aggiornamento

vedo che c'è una vasta cocensuse cosa significa "ombra". E dal punto di vista formale il compilatore fa esattamente ciò che significava anche.

Tuttavia, IMHO, la bandiera non è pratica. Per esempio comunemente usato setter/getter idioma:

class A { 
    void prop(int prop); // setter 
    int prop() const;  // getter 

    int prop; 
}; 

Sarebbe bello se ci sarà una bandiera di avvertimento che non emetterà avviso nel caso, ma avviserà nel caso in cui "int a" nasconde "int un".

Aggiunta di -Whadow sul mio codice legacy genera tonnellate di avvisi, mentre di tanto in tanto scopro bug causati dal problema di "shadowing".

Non mi dispiace come sarà chiamato "-Wmuch_more_practical_and_interesting_shadow" o "-Wfoooooo".

Quindi, c'è altro flag di avviso gcc che fa ciò che ho descritto?

Aggiornamento 2

Non solo me pensa -Wshadow in qualche modo non utile link text. Io non sono solo :) Controlli meno rigorosi potrebbero essere molto più utili.

+4

Il tuo "linguaggio comunemente usato" non è nemmeno un codice legale. –

risposta

14

Questo sembra essere risolto nelle versioni più recenti di GCC.

From version 4.8 changelog:

The option -Wshadow no longer warns if a declaration shadows a function declaration, 
unless the former declares a function or pointer to function, because this is a common 
and valid case in real-world code. 

E fa riferimento a pensieri di Linus Torvalds sul tema: https://lkml.org/lkml/2006/11/28/253

Purtroppo il nuovo compilatore del sistema embedded dove sto attualmente lavorando si basa ancora su gcc 4.6.

+0

+1 per questa risposta. -1 a GCC per questa decisione, però! –

+5

In realtà a partire da GCC 4.8.2 questo problema con -Wshadow è ancora lì. Se leggi questo problema di bugzilla: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57709 è confermato che _member_ funzioni che hanno lo stesso nome di un parametro di funzione, come nel tuo esempio, generano ancora il avviso ombra. A partire da GCC 4.8, solo le funzioni libere hanno soppresso questo errore. Sembra che dovremo aspettare fino a GCC 5.0 per avere questo lavoro come ti aspetteresti. – ScottG

15

Il fatto che il parametro abbia un tipo diverso dalla funzione membro non influisce sul fatto che il parametro ombreggia la funzione membro.

Perché dovresti aspettarti che non ci sia un avvertimento a riguardo?

+0

Sono interessante nei casi in cui la variabile nasconde variabile. Questo potenzialmente un bug. Ma il caso in cui la variabile "nasconde" una funzione non è interessante. – dimba

+4

@idimba: non sono d'accordo. Un puntatore di funzione può essere memorizzato in una variabile. Anche una variabile può avere un 'operator()' definito per questo in modo che possa essere invocato come una funzione. – Troubadour

+7

Potrebbe non essere interessante, ma * è * ombreggiato. E l'avvertimento è chiamato -Whadow, non -Winteressante. Quindi mi aspetterei che avvisasse quando un nome ne nasconde un altro, non quando @idimba pensa che il codice sia "interessante". – jalf

6

Fa esattamente quello che dice sulla scatola. Ti avvisa di shadowing.

All'interno della funzione setLen, sono presenti due simboli che condividono lo stesso nome. len è il nome di un parametro di funzione e anche il nome di una funzione.

One ombre il nome dell'altro, quindi quando si scrive codice che si riferisce a len, potresti non ottenere il risultato desiderato. Dal momento che hai chiesto al compilatore di avvertirti sui simboli ombreggiato l'uno per l'altro, questo è ciò che ti avvisa.

9

Non capisco perché insisti solo su alcuni tipi specifici di ombreggiamento. L'ombra è ombreggiante e il pericolo è lo stesso anche se i tipi sono diversi e anche se una variabile ombreggia una funzione, come nel tuo caso. Il pericolo di shadowing è che il codice potrebbe fare qualcosa di diverso da ciò che il suo autore voleva che facesse.

Questo, a proposito, può facilmente verificarsi quando una variabile ombreggia una funzione, poiché in C++ la distinzione tra i due è molto più sottile di quanto potrebbe sembrare a prima vista.

Per esempio, ecco una variabile ombre una funzione

struct L { 
    void operator()(); 
}; 

struct A { 
    void len(); 

    A(L len) { 
    len(); 
    // Intended to call the member function. Instead got a call to the functor 
    } 
}; 

e penso che sia abbastanza evidente che a causa del pedinamento del codice potrebbe fare qualcosa l'autore non aveva intenzione di fare.

2

Sì, possiamo mettere a punto questo avviso per avvisare solo quando lo shadowing potrebbe essere pericoloso. Ad esempio non ombra per

void set (int cosa) .. int quello() const ..

ma avvertono per shadowning variabile locale e per l'esempio funtore sopra.

Per essere più precisi, avvertire quando lo shadowing potrebbe essere pericoloso, quando l'intento del programma di scrittura del codice potrebbe non essere chiaro. Nel caso di un parametro int e una funzione membro con lo stesso nome, è chiaro che l'autore non desidera che il membro venga chiamato quando fa riferimento al parametro.

Trovo che questo avviso ombra sia una buona idea, molto utile, ha solo bisogno di un po 'più di riflessione per non avvisare su casi perfettamente sicuri e chiari. Ad esempio, posso vivere con argomenti necessari per avere un prefisso o qualcosa del genere, ma preferisco nomi chiari e semplici.