2010-01-29 17 views
5

Questo codice è ambiguo o è perfettamente valido (approvato dagli standard/ha un comportamento coerente per qualsiasi compilatore esistente)?È ambiguo o va perfettamente bene?

struct SCustomData { 
    int nCode; 
    int nSum; 
    int nIndex; 
    SCustomData(int nCode, int nSum, int nIndex) 
     : nCode(nCode) 
     , nSum(nSum) 
     , nIndex(nIndex) 
    {} 
}; 

edit:
Sì, mi riferisco al fatto che le variabili membro hanno lo stesso nome con i parametri formali del costruttore.

+3

Sarò onesto, ho dovuto leggerlo due volte ... Sarei probabilmente uno sviluppatore infelice se dovessi continuare a leggere lo stesso codice due volte. –

+3

Scusa, ma cosa dovrebbe essere ambiguo a riguardo? Sembra diretto a me. –

+0

Ciò che è ambiguo (per l'umano) è avere lo stesso identificatore sia per un attributo sia per un parametro ... –

risposta

6

No, in questo caso non ci sono ambiguità, ma prendere in considerazione seguente:

struct SCustomData { 
//... 
    void SetCode(int nCode) 
    { 
      //OOPS!!! Here we do nothing! 
      //nCode = nCode; 

      //This works but still error prone 
      this->nCode = nCode; 
    } 
}; 

Si dovrebbe richiamare l'attenzione su uno degli stili di codifica esistenti. Per esempio, General Naming Rule in Google C++ Coding Styles o leggi l'eccellente libro "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices" di Herb Sutter e Andrei Alexandrescu.

+0

Semplice regola uso tutto il tempo: prima lettera maiuscola per i parametri, minuscolo per campi privati. –

+0

Preferisco lo stile di Sutter: Camel Case - per i parametri (codice - in questo esempio), cammello Case e underscore (_) - per i campi privati ​​(code_ - in questo esempio). –

4

Il tuo esempio non è ambiguo (per me), ma non è una buona pratica, perché può diventare rapidamente ambiguo come l'inferno.

È da un po 'che non scrivo nessun C++ in rabbia, quindi suppongo che cosa farà.
Hai KNOW cosa farà? Sei sicuro?

class Noddy 
{ 
    int* i; 
    Noddy(int *i) 
    : i(i) 
    { 
     if(i == NULL) 
      i = new int; 
    } 
}; 
+1

Sì, so cosa farà, ma non scommetterei i soldi che fanno i miei colleghi :) –

+0

Dimmi Dimmi, dimmi! L'interiore "i" si riferisce al "più vicino dichiarato": l'argomento? (L'elenco di inizializzazione può ovviamente riferirsi solo al membro) – xtofl

+2

@xtofl: corretto, per fare ciò che "sembra" come dovrebbe fare, dovrebbe essere "questo-> i" all'interno delle parentesi graffe {} –

1

Se ti stai riferendo a usare lo stesso nome per i membri e gli argomenti del costruttore, allora va benissimo. Tuttavia, potresti trovare alcune persone che insistono sul fatto che sia una cattiva pratica per qualche motivo.

Se è necessario accedere ai membri nel corpo del costruttore, è necessario prestare attenzione, fornire gli argomenti con nomi diversi oppure utilizzare this-> per accedere ai membri.

Se si fa riferimento all'utilizzo di verruche pseudounguari per ricordare alle persone che gli interi sono numeri interi, ciò è tecnicamente consentito, ma non ha assolutamente alcun vantaggio e rende il codice molto più difficile da leggere. Per favore, non farlo.

+1

Come una di "quelle persone", le mie ragioni sono a) l'OP dovette chiedere a questo proposito - quindi probabilmente gli altri leggeranno tale codice eb) vedrà il tuo secondo par. –

+1

@Neil: (a) non è possibile scrivere C++ in modo tale che le persone che lo leggono non abbiano bisogno di sapere C++, (b) sono completamente d'accordo, in una funzione con un corpo non vuoto, nascondendo le variabili membro con i parametri sta chiedendo problemi. La differenza è che in (b), è facile confondere accidentalmente i due anche se conosci bene la lingua, solo perché ti sei dimenticato del nascondiglio da un minuto all'altro. Ciò si traduce in bug. In (a), c'è solo una intenzione plausibile del codice e la domanda è se si è consapevoli che è legale. Ciò si traduce in un momento educativo. –

1

In generale, ho prefisso variabili di istanza con caratteri di sottolineatura e parametri con nome nel costruttore senza prefissi. Per lo meno, questo disambiguerebbe i parametri dalle variabili di istanza. Rende anche la vita meno frenetica se si inizializza all'interno del corpo del costruttore.

struct SCustomData { 
    int _nCode; 
    int _nSum; 
    int _nIndex; 
    SCustomData(int nCode, int nSum, int nIndex) 
     : _nCode(nCode), _nSum(nSum), _nIndex(nIndex) 
    {} 
}; 

// Alternatively 
struct SCustomData { 
    int _nCode; 
    SCustomData(int nCode) 
    { 
     this->_nCode = nCode; 
    } 
}; 

Non mi piace impilare le variabili nel modo in cui è stato scritto nella domanda. Mi piace risparmiare spazio verticale ed è anche più facile leggere da sinistra a destra. (Questa è una preferenza personale della mia, non una regola obbligatoria o qualcosa di simile.)

+4

Sfortunatamente, i nomi degli identificatori che iniziano con il carattere di sottolineatura sono riservati sia in C che in C++. – aib

0

È perfettamente conforme allo standard, ma ci sono compilatori che non accettano variabili membro aventi lo stesso nome dei parametri di costruzione . In effetti, ho dovuto cambiare la mia libreria open source per questo motivo. Vedi this patch

1

Direi che questo è perfettamente a posto.

È il mio stile preferito per i costruttori che utilizzano l'elenco di inizializzazione e non hanno alcun codice. Penso che riduca la confusione perché è ovvio quale parametro del costruttore va a quale membro.

Problemi correlati